该关键字static在 C++ 中具有多种含义,我觉得这很令人困惑,我永远无法思考它实际上应该如何工作。
static
据我了解,有static存储持续时间,这意味着在全局情况下它会持续整个程序的生命周期,但是当您谈论本地时,这意味着它默认为零初始化。
C++ 标准对带有关键字的类数据成员这么说static:
3.7.1 静态存储时长[basic.stc.static]
3 关键字 static 可用于声明具有静态存储持续时间的局部变量。 4 在类定义中应用于类数据成员的关键字 static 给出了数据成员静态存储的持续时间。
3 关键字 static 可用于声明具有静态存储持续时间的局部变量。
4 在类定义中应用于类数据成员的关键字 static 给出了数据成员静态存储的持续时间。
局部变量 是什么意思?那是一个函数局部变量吗?因为还有当你声明一个本地函数时static,它只初始化一次,第一次进入这个函数。
它也只讨论了关于类成员的存储持续时间,它不是特定于实例的,这也是一个static否的属性?或者是存储时间?
那么static文件范围的情况呢?默认情况下是否所有全局变量都被认为具有静态存储持续时间?以下(来自第 3.7.1 节)似乎表明了这一点:
1 所有没有动态存储时长、没有线程存储时长、 非本地 变量都有静态存储时长。这些实体的存储应持续整个程序(3.6.2、3.6.3)
与static变量的链接有何关系?
这整个static关键字是彻头彻尾的混乱,有人可以澄清它英语的不同用途,还告诉我 什么时候 初始化一个static类成员?
static 变量存在于定义它的翻译单元 的“生命周期”中,并且:
constexpr
std::string::npos
位置作为代码:
static std::string namespaceScope = "Hello"; void foo() { static std::string functionScope= "World"; } struct A { static std::string classScope = "!"; };
在执行翻译单元中的任何函数之前(可能在main开始执行之后),该翻译单元中具有静态存储持续时间(命名空间范围)的变量将被“常量初始化”(constexpr在可能的情况下,否则为零),然后非本地人 按照它们在翻译单元中定义的顺序std::string="HI";正确地“动态初始化”(对于那些不是 这样的事情constexpr)。最后,函数局部静态将在第一次执行“到达”声明它们的行时被初始化。所有static变量都以初始化的相反顺序销毁。
main
std::string="HI";
获得这一切的最简单方法是将所有未constexpr初始化的静态变量设置为函数静态局部变量,这样可以确保在您尝试使用它们时正确初始化所有静态变量/全局变量,从而防止静态初始化命令惨败。
T& get_global() { static T global = initial_value(); return global; }
小心,因为当规范说命名空间范围变量默认具有“静态存储持续时间”时,它们的意思是“翻译单元的生命周期”位,但这并不 意味着 它不能在文件之外访问。
明显更直接,static通常用作类成员函数,很少用于独立函数。
静态成员函数与常规成员函数的不同之处在于它可以在没有类实例的情况下调用,并且由于它没有实例,因此它不能访问类的非静态成员。当您希望为绝对不引用任何实例成员的类或管理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 }
自由函数意味着该static函数不会被任何其他翻译单元引用,因此链接器可以完全忽略它。这有几个目的:
static void log(const char*) {}