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

为什么静态数据成员必须在C++中定义?,c++,C++,我总是很难发现为什么我的代码中会出现对静态变量的未定义引用,我总是会遇到以下问题: 我知道我需要在类声明之外定义数据 在示例中: class Helloworld { public: static int x; void foo(); }; int Helloworld::x = 0; // Or whatever is the most appropriate value // for initializing x. No

我总是很难发现为什么我的代码中会出现对静态变量的未定义引用,我总是会遇到以下问题:

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

在示例中:

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。为什么我需要为下面的静态示例这样做

class A {
    public: 
        static B b;
}

B A::b

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

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

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


信息和。

静态成员在创建任何对象之前就已经存在,这就是为什么它们是静态的。因此,它们的初始化不会在第一个实例上发生,它们已经在那里了

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

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

信息和

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

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

随着编译器变得越来越智能,C++17的出现,事实证明编译器真的可以解决这个问题。在C++17中,可以将静态成员指定为内联变量,编译器/链接器将对其进行排序

class A {
    public: 
        static inline B b; // There, an inline variable default initialized.
};
但是作为类实例的静态成员呢?为什么编译器不使用默认构造函数为我创建一个实例

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

随着编译器变得越来越智能,C++17的出现,事实证明编译器真的可以解决这个问题。在C++17中,可以将静态成员指定为内联变量,编译器/链接器将对其进行排序

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

您需要在类外部定义B,原因与您必须在类外部定义x相同:因为它是静态成员。作为基本类型int或类类型B与此无关

您需要在类外定义B,原因与您必须在类外定义x相同:因为它是静态成员。作为基本类型int或类类型B与此无关

为什么编译器不使用默认构造函数为我创建一个实例?它应该在哪里这样做?如果是这样,那么每个包含头的文件都将创建一个实例。因此,您将有几个实例。这就是为什么您需要告诉它在哪里定义它,也就是在哪个cpp文件中定义它。C++17引入了内联,允许在每个cpp文件中有多个定义,但最终只保留其中一个。@NikosC。这就是让我明白为什么它不会在标题中定义的答案,谢谢!为什么编译器不使用默认构造函数为我创建一个实例?它应该在哪里这样做?如果是这样,那么每个包含头的文件都将创建一个实例。因此,您将有几个实例。这就是为什么您需要告诉它在哪里定义它,也就是在哪个cpp文件中定义它。C++17引入了内联,允许在每个cpp文件中有多个定义,但最终只保留其中一个。@NikosC。这就是让我明白为什么它不会在标题中定义的答案,谢谢!请注意,内联变量的代价很小:初始化变得更加复杂,因为需要保证单个转换单元的初始化顺序从上到下,并且内联变量位于多个转换单元中。请注意,内联变量的代价很小:初始化变得更加复杂,因为需要保证单个转换单元的初始化顺序从上到下,并且内联变量位于多个转换单元中。请注意,内联变量的代价很小:初始化变得更加复杂,因为需要保证从上到下的初始化顺序 r表示单个转换单元,内联变量表示多个转换单元。请注意,内联变量的代价很小:初始化变得更加复杂,因为需要保证单个转换单元的初始化顺序从上到下,并且内联变量位于多个转换单元中。