前提
C++ is a statically typed language, which means that types are checked at compile time. C++是一门静态语言,所以才有类型的check,所以需要考虑是否为static静态类型
单词pimer的释义
这纯属本人捏造的趣事。prime通常指一个人一生中最活跃,最黄金的阶段,且Prime often means "main."
作为程序员对main函数,再熟悉不过,所以《c++ primer》就是一本把C++从main函数出发以后的几乎所有细枝末节给你铺开
讲的明明白白的一本书,它也可能是你一生中最活跃,最黄金的时候与它常打交道的一本书了。
static
有一个局部变量,它的生存期在对函数的调用中持续,这是很有用的。 如果局部静态没有显式初始化式,则对其进行值初始化,这意味着将内置类型的局部静态初始化为零。
cpp
size_t count_calls()
{
static size_t ctr = 0; // value will persist across calls
return ++ctr;
}
int main()
{
for (size_t i = 0; i != 10; ++i)
cout << count_calls() << endl;
return 0;
}
类有时需要与类关联的成员,而不是与类类型的单个对象关联的成员。
cpp
class Account {
public:
void calculate() { amount += amount * interestRate; }
static double rate() { return interestRate; }
static void rate(double);
private:
std::string owner;
double amount;
static double interestRate;
static double initRate();
};
The static members of a class exist outside any object.
We can access a static member directly through the scope operator:
cpp
double r;
r = Account::rate(); // access a static member using the scope operator
即使静态成员不是其类的对象的一部分,也可以使用类类型的对象、引用或指针来访问静态成员:
cpp
Account ac1;
Account& ac3 = ac1;
Account* ac2 = &ac1;
// equivalent ways to call the static member rate function
r = ac1.rate(); // through an Account object or reference
r = ac3.rate(); // through an Account reference
r = ac2->rate(); // through a pointer to an Account object
成员函数可以直接使用静态成员,不需要作用域操作符:
cpp
class Account {
public:
void calculate() { amount += amount * interestRate; }
private:
double amount;
static double interestRate;
// remaining members as before
};
初始化静态成员变量
cpp
// define and initialize a static class member
double Account::interestRate = initRate();
static const类型的使用
cpp
class Account {
public:
static double rate() { return interestRate; }
static void rate(double);
private:
static constexpr int period = 30;// period is a constant expression
double daily_tbl[period];
static double interestRate;
};
如果在类内部提供了初始化式,则成员的定义不能指定初始值:
cpp
// definition of a static member with no initializer
constexpr int Account::period; // initializer provided in the class definition
静态数据成员可以具有不完整类型
非静态数据成员只能声明为指向其类对象的指针或引用:
cpp
class Bar {
public:
// ...
private:
static Bar mem1; // ok: static member can have incomplete type
Bar* mem2; // ok: pointer member can have incomplete type
Bar mem3; // error: data members must have complete type
};
静态成员与普通成员的另一个区别是,可以将静态成员用作默认实参
cpp
class Screen {
public:
// bkground refers to the static member
// declared later in the class definition
Screen& clear(char = bkground);
private:
static const char bkground;
};
继承树中的static成员,整个层次结构只定义了一个这样的成员。
cpp
class Base {
public:
static void statmem();
};
class Derived : public Base {
void f(const Derived&);
};
静态成员服从普通的访问控制。如果成员在基类中是私有的,则派生类无法访问它。假设成员是可访问的,则可以通过基类或派生类使用静态成员:
cpp
void Derived::f(const Derived& derived_obj)
{
Base::statmem(); // ok: Base defines statmem
Derived::statmem(); // ok: Derived inherits statmem
// ok: derived objects can be used to access static from base
derived_obj.statmem(); // accessed through a Derived object
statmem(); // accessed through this object
}
类模板的static成员
cpp
template <typename T> class Foo {
public:
static std::size_t count() { return ctr; }
// other interface members
private:
static std::size_t ctr;
// other implementation members
};
模板类静态实例化
cpp
// instantiates static members Foo<string>::ctr and Foo<string>::count
Foo<string> fs;
// all three objects share the same Foo<int>::ctr and Foo<int>::count members
Foo<int> fi, fi2, fi3;
模板类静态初始化
cpp
template <typename T>
size_t Foo<T>::ctr = 0; // define and initialize ctr
模板类静态成员的使用
cpp
Foo<int> fi; // instantiates Foo<int> class
// and the static data member ctr
auto ct = Foo<int>::count(); // instantiates Foo<int>::count
ct = fi.count(); // uses Foo<int>::count
ct = Foo::count(); // error: which template instantiation?
嵌套类静态成员定义
cpp
// defines an int static member of QueryResult
// which is a class nested inside TextQuery
int TextQuery::QueryResult::static_mem = 1024;
static_assert
水平不够,未来有时间来补上
static_cast
- 当将较大的算术类型赋值给较小的类型时,static_cast通常很有用。强制类型转换告知程序的读者和编译器,我们知道并且不关心潜在的精度损失。将较大的算术类型赋值给较小的类型时,编译器通常会生成警告。当我们执行显式强制转换时,警告消息将被关闭。
cpp
// cast used to force floating-point division
double slope = static_cast<double>(j) / i;
- 对于执行编译器不会自动生成的转换,static_cast也很有用。例如,可以使用static_cast来检索存储在void*指针.
cpp
void* p = &d; // ok: address of any nonconst object can be stored in a void*
// ok: converts void* back to the original pointer type
double *dp = static_cast<double*>(p);
- static_cast更深的运用,路还远,任重而道远呐
C++挑马桶基本功
- for循环的简单遍历,不在手写低效for循环。
cpp
// print words of the given size or longer, each one followed by a space
for_each(wc, words.end(),
[](const string &s){cout << s << " ";});
cout << endl;
- 自从C++11有了智能指针,C++里一切稍微占据大量内存的数据都应该用智能指针,因为性能的缘故
cpp
// C++万物可指针
class HugeData {
public:
HugeData() {
}
void init() {
data_ = new std::list<HugeData*>{};
}
void work() {
}
private:
static std::list<HugeData*>* data_;
};
// 但是智能指针岂不更香
class HugeData {
public:
HugeData() {}
void init() {
data_ = std::make_shared<std::list<std::shared_ptr<HugeData>> >();
}
void work() {}
private:
static std::shared_ptr < std::list<std::shared_ptr<HugeData>> > data_;
};