我总是很难发现为什么我的代码中会出现“对静态变量的未定义引用”,而我总是会遇到以下问题:
Undefined reference to static variable c++
Undefined reference to static variable
我知道我需要在类声明之外定义数据。
在示例中:
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;
我不需要在B b
类声明之外定义A
。为什么在下面的静态示例中需要这样做?
class A {
public:
static B b;
}
B A::b
答案 0 :(得分:4)
静态成员在创建任何对象之前就已经存在,这使它们成为静态。因此,它们的初始化不会在一开始就发生,而是已经存在。
它们实际上是类范围内的全局变量。
也就是说,您可以使用inline
修饰符在类内对其进行初始化,而无需进行类外声明。
答案 1 :(得分:4)
但是作为类实例的静态成员呢?为什么简单地编译器不会使用默认构造函数为我创建实例?
但要放在哪里?在C ++ 17之前进行此操作的合理性是,在一个定义规则下,必须只有一个这样的静态成员定义。因此,即使对象要进行默认的初始化,也要由程序员确切地定义该定义应驻留在哪个翻译单元中。不信任编译器“做正确的事” TM 。
随着编译器变得越来越聪明,以及C ++ 17的出现,事实证明编译器确实可以解决这个问题。在C ++ 17中,您可以将静态成员指定为内联变量,编译器/链接器会对其进行整理。
class A {
public:
static inline B b; // There, an inline variable default initialized.
};
答案 2 :(得分:0)
您需要在类外定义B,其原因与在类外定义x的原因相同:因为它是静态成员。是原始类型(int)或类类型(B)与它无关!