静态成员变量是一种特殊的成员变量,类体中的数据成员声明时前面加上关键字static,即成为该类的静态数据成员。首先罗列一下C++静态成员变量的一些知识点。
- 所有对象共享共享静态成员变量的同一份内存:
静态成员变量属于类,不属于某个具体的对象。即使创建多个对象,也只为其分配一份内存,所有对象使用的是这份内存中的数据,当某个对象修改了静态成员变量的值,也会影响到其他的对象。static成员变量不占用对象内存,在所有对象外开辟内存,不创建对象也可以访问。 - 编译阶段就分配内存:
对于静态成员变量而言,它们的生命周期与类的生命周期相关联,而不是与类的实例的生命周期相关联。编译时在静态数据区分配内存,到程序结束时才释放。这就意味着static成员变量不随对象的创建而分配内存,也不随对象的销毁而释放内存。而普通成员变量在对象创建时分配内存,在对象销毁时释放内存。
- 静态成员变量实际上就是类域中的全局变量,类内声明,类外进行初始化操作。
- 初始化时不受private和protected访问限制。
上述知识点体现在如下代码中:
class Person
{
public:
static int m_A;
private:
static int m_B;
protected:
static int m_C;
};
int Person::m_A = 99;
//初始化不受private访问限制
int Person::m_B = 100;
int Person::m_C = 100;
int main()
{
// 通过对象进行访问静态成员变量
Person p1;
cout <<"p1.m_A: " << p1.m_A << endl;
//所有对象共享共享静态成员变量的同一份内存
p1.m_A = 66;
Person p2;
cout << "p2.m_A: " << p2.m_A << endl;
// 通过类名进行访问静态成员变量
cout <<"Person::m_A: " << Person::m_A << endl;
return 0;
}
输出结果如下:
那为什么C++的静态成员变量要设计成必须类内声明,类外显式初始化呢?为什么不能像其他成员变量一样会默认初始化呢?
C++中的静态成员变量是属于整个类的,而不是属于类的任何特定实例。如果C++为静态成员变量提供默认初始化值,那么可能会导致以下问题:
- 多次定义:
如果静态成员变量有默认初始化值,且在多个源文件中都包含了该类的定义,那么编译器会在每个源文件中生成对静态成员变量的初始化代码,从而导致链接时的多重定义错误。
假设有一个类MyClass,其中包含一个静态成员变量staticVar ,如果C++允许静态成员变量默认初始化,那么可能会出现以下情况:
MyClass.h:// MyClass.h #pragma once class MyClass { public: static int staticVar; // 静态成员变量声明 };
File1.cpp:
// File1.cpp #include "MyClass.h" // 如果静态成员变量有默认初始化值 // 那么这里可能会生成初始化代码 // static int MyClass::staticVar = defaultValue;
File2.cpp:
// File2.cpp #include "MyClass.h" // 同样,这里也可能生成初始化代码 // static int MyClass::staticVar = defaultValue;
如果staticVar有默认初始化值,并且同时在File1.cpp和File2.cpp中包含了对MyClass的定义,那么在链接时就会出现多次定义的错误。因为每个源文件中都尝试对staticVar进行初始化。
类似于普通变量的重定义//重复定义会报错 int a = 10; int a = 11;
为了避免这种问题,C++不允许对静态成员变量进行默认初始化,而需要在类外部单独进行一次定义和初始化。
class Person { public: static int m_A; private: static int m_B; protected: static int m_C; }; int Person::m_A = 99; //初始化不受private访问限制 int Person::m_B = 100; int Person::m_C = 100;
注意使用作用域解析运算符
::
来访问静态成员变量,而不是使用实例化对象后再用.
来访问。在C++中,静态成员变量属于类,而不是类的实例。我们使用Person::m_A
来表示它属于MyClass类,而不是MyClass类的实例。
这样可以明确地表示这是一个静态成员变量,并且不依赖于任何特定的类实例。 -
不确定性:
静态成员变量的默认初始化值可能会因编译器、平台或环境的不同而产生差异,这会导致程序行为的不确定性。
---------------------------------------------------------------------------------------------------------------------------------如果有讲的不对的,请大家指正!