C++中的静态成员
在一个类的定义中,关键字 static
声明一个不属于类实例的成员。
一些细节
如果类定义中某个成员的声明说明符包含关键字 static
,那么它就是类的静态成员。静态成员的名称不能和包含的类相同。
需要注意的是,在类定义中声明的静态变量是一个声明而不是定义,并且成员可以是一个不完整类型(除了void),类型也可以是成员声明所在的类型,例如如下代码:
struct Foo; struct S { static int a[]; // 这是一个声明,且是不完整类型 static Foo x; // 这是一个声明,且是不完整类型 static S s; // 声明,成员的类型为S,为成员所在的类型,因为S是一个不完整的类型,所以s也是一个不完整的类型 }; int S::a[10]; // 定义,完整的类型 struct Foo {}; Foo S::x; // 定义,完整的类型 S S::s; // 定义,完整的类型
如果声明使用了 constexpr
或者 inline
(从C++17开始),那么成员必须拥有完成类型。
静态成员遵循类成员访问规则(class member rules)。
静态成员函数
静态成员函数不能是 const
,volatile
,virtual
,引用限定(ref-qualified)。
静态数据成员
静态数据在整个程序中只有一个实例,且生命周期为静态存储周期,但是如果使用了 thread_local
关键字,那么每个线程都会有一个该对象,且生命周期为线程存储周期。
内联的静态成员
从 C++17 开始,静态成员可以是内联的,如下代码所示:
struct X { inline static int a = 10; }
一个内联的静态数据成员可以被定义在类中,且可以拥有初始化器。
常量静态成员
如果一个整形或者枚举类型的静态数据成员被声明为 const
,那么可以在类中直接通过一个常量表达式初始化它,例如如下代码:
struct X { const static int n = 1; const static int m{2}; const static int k; }; const int X::k = 3;
从 C++11 开始,如果(LiteralType )静态成员被声明为 constexpr
,那么必须在类定义中通过常量表达式初始化器初始化它。如果一个 const
或者 constexpr
静态数据成员被 odr-used 了,那么在命名空间作用域仍然需要一个定义,但是它不能有初始化器。
但是从 C++17开始,如果静态常量数据成员是内联的 inline
,那么可以不需要定义,需要注意的是,constexpr
已经暗含了 inline
,因此一个 constexpr
静态成员也可以不需要定义,例如如下代码:
struct X { static const int n = 1; static constexpr int m = 4; }; const int *p = &X::n, *q = &X::m; // X::n and X::m ord 使用 const int X::n; // 所以X::n需要一个定义 constexpr int X::m; //但是X::m不需要,虽然也允许
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)