变量:
静态变量存在于定义它的翻译单元的“生命周期”中,并且:
If it's in a namespace scope (i.e. outside of functions and classes), then it can't be accessed from any other translation unit. This is known as "internal linkage" or "static storage duration". (Don't do this in headers except for constexpr. Anything else, and you end up with a separate variable in each translation unit, which is crazy confusing)
If it's a variable in a function, it can't be accessed from outside of the function, just like any other local variable. (this is the local they mentioned)
class members have no restricted scope due to static, but can be addressed from the class as well as an instance (like std::string::npos). [Note: you can declare static members in a class, but they should usually still be defined in a translation unit (cpp file), and as such, there's only one per class]
位置代码:
static std::string namespaceScope = "Hello";
void foo() {
static std::string functionScope= "World";
}
struct A {
static std::string classScope = "!";
};
Before any function in a translation unit is executed (possibly after main began execution), the variables with static storage duration (namespace scope) in that translation unit will be "constant initialized" (to constexpr where possible, or zero otherwise), and then non-locals are "dynamically initialized" properly in the order they are defined in the translation unit (for things like std::string="HI"; that aren't constexpr). Finally, function-local statics will be initialized the first time execution "reaches" the line where they are declared. All static variables all destroyed in the reverse order of initialization.
要做到这一点,最简单的方法是将所有未被构造变量初始化的静态变量初始化为函数静态局部变量,这可以确保当您尝试使用它们时,无论如何都正确初始化了所有静态/全局变量,从而防止静态初始化顺序的混乱。
T& get_global() {
static T global = initial_value();
return global;
}
要小心,因为当规范说名称空间作用域变量默认具有“静态存储持续时间”时,它们指的是“翻译单元的生命周期”位,但这并不意味着不能在文件外部访问它。
功能
更直接的是,static通常用作类成员函数,很少用于独立函数。
静态成员函数与常规成员函数的不同之处在于,它可以在没有类实例的情况下被调用,并且由于它没有实例,所以它不能访问类的非静态成员。当你想为一个绝对不引用任何实例成员的类创建一个函数,或者用于管理静态成员变量时,静态变量非常有用。
struct A {
A() {++A_count;}
A(const A&) {++A_count;}
A(A&&) {++A_count;}
~A() {--A_count;}
static int get_count() {return A_count;}
private:
static int A_count;
}
int main() {
A var;
int c0 = var.get_count(); //some compilers give a warning, but it's ok.
int c1 = A::get_count(); //normal way
}
静态自由函数意味着该函数不会被任何其他翻译单元引用,因此链接器可以完全忽略它。这有几个目的:
可以在cpp文件中使用,以确保该函数永远不会从任何其他文件中使用。
可以放在头文件中,每个文件都有它自己的函数副本。没什么用,因为内联做的几乎是同样的事情。
通过减少工作来加快链接时间
可以在每个翻译单元中放入同名的函数,它们都可以做不同的事情。例如,您可以在每个cpp文件中放入一个静态void log(const char*){},并且它们都可以以不同的方式进行日志记录。