为什么必须在C++中定义静态数据成员?

Why static data members must be defined in C++?

本文关键字:定义 静态 数据成员 C++ 为什么      更新时间:2023-10-16

我总是很难发现为什么在我的代码中得到"对静态变量的未定义引用",我总是以这些问题告终:

对静态变量 c++ 的未定义引用

对静态变量的未定义引用

我知道我需要在类声明之外定义我的数据。

在示例中:

class Helloworld {
public:
static int x;
void foo();
};
int Helloworld::x = 0; // Or whatever is the most appropriate value
// for initializing x. Notice, that the
// initializer is not required: if absent,
// x will be zero-initialized.

我必须将 x 启动到某个值。但是作为类实例的静态成员呢?为什么编译器不会使用默认构造函数为我创建实例?

如果我写

class A {
public: 
B b;
}

那我可以做

A a;
a.b;

我不需要在A类声明之外定义B b。为什么我需要为下面的静态示例执行此操作?

class A {
public: 
static B b;
}
B A::b

静态成员在创建任何对象之前就存在,这就是使它们成为静态成员的原因。因此,它们的初始化不会在第一次发生,它们已经存在。

它们实际上是类范围内的全局变量。

也就是说,您可以使用inline修饰符在类内初始化它们,而无需类外声明。

信息在这里和这里。

但是

作为类实例的静态成员呢?为什么编译器不会使用默认构造函数为我创建实例?

但是把它放在哪里?在 C++17 之前,这样做的理由是,在一个定义规则下,静态成员必须只有一个这样的定义。因此,程序员可以准确指定该定义应该位于哪个翻译单元中,即使对象要进行默认初始化也是如此。编译器不被信任为"做正确的事">TM。

随着编译器变得越来越聪明,C++17 的出现,事实证明编译器真的可以弄清楚。在 C++17 中,您可以将静态成员指定为内联变量,编译器/链接器将对其进行排序。

class A {
public: 
static inline B b; // There, an inline variable default initialized.
};

你需要在类外定义 B,原因与在类外定义 x 的原因相同:因为它是一个静态成员。作为基元类型(int(或类类型(B(与它无关!