C++ static关键词有三种完全不同的用途
通常他们在main函数之前初始化,存活到 main函数结束
static int a ; // static 变量
在一个函数体(严格的说是 block scope) 内部,用static 变量就是 static local 变量。
这类变量一般在第一次运行到这段代码就初始化(付出的代价就是每次运行到这里就要检查一遍是否被 初始化)
- void func(){
-
- static int a ; // static local 变量
- }
- // A.h
- class A
- {
-
- static int a ;
- }
于是C++设计者想出了这么一个方案,再加一条语句用来专门生成符号,顺便初始化。
- // A.h
- class A {
-
- static int a; // 不生成符号
- }
-
- // A.cpp
-
- include "A.h"
- int A::a; // 生成一个符号,并初始化
很显然,变量a 的初始化是在类外进行的,头文件 类内不能初始化,如果我们一定要在类内初始化了 ??我们可以这样做
- // A.h
-
- class A
- {
-
- static const int a = 0 ; // 不生成符号,但是在编译时可以读取 a的值
- }
-
- // A.cpp
- #include “A.h”
- int A::a; // 在类外提供一个符号,让其在链接时可以找到符号。
那么如何避免:总不能让每个翻译单元都有一个符号把了 ??
C++17引入了 inline修饰符,添加了 inline修饰符后,就可以每个翻译单元生成一个符号,然后链接器去链接的时候,选择其中一个
- // A.h
-
- class A {
-
- static inline int a = 2; // 生成符号,可以取地址 , 并且支持类内初始化。
- }
然后C++17以后,constexpr 的 static member变量默认 inline ,所以你可以这样写
- // A.h
-
- class A {
-
- static constexpr int a = 3; //生成符号,可以取地址,并且支持初始化
-
- }