为什么需要显式定义静态变量?

2022-01-05 00:00:00 static c++

在课堂上:

class foo
{
public:
    static int bar; //declaration of static data member
};

int foo::bar = 0; //definition of data member

必须显式定义静态变量,否则会导致

We have to explicitly define the static variable, otherwise it will result in a

对foo::bar"的未定义引用

我的问题是:

请注意,这不是重复之前询问的对静态变量的未定义引用问题.这个问题旨在询问显式定义静态变量背后的原因.

Please note that this is NOT a duplicate of previously asked undefined reference to static variable questions. This question intends to ask the reason behind explicit definition of a static variable.

推荐答案

从一开始 C++ 语言就和 C 一样,都是建立在独立翻译的原则之上的.每个翻译单元都由编译器本身独立编译,无需了解其他翻译单元.整个程序只是在稍后,在链接阶段才聚集在一起.链接阶段是链接器看到整个程序的最早阶段(它被视为由编译器本身准备的目标文件的集合)).

From the beginning of time C++ language, just like C, was built on the principle of independent translation. Each translation unit is compiled by the compiler proper independently, without any knowledge of other translation units. The whole program only comes together later, at linking stage. Linking stage is the earliest stage at which the entire program is seen by linker (it is seen as collection of object files prepared by the compiler proper).

为了支持独立翻译这一原则,必须在一个翻译单元中定义每个具有外部链接的实体,并且只能在一个翻译单元中定义.用户负责在不同的翻译单元之间分配这些实体.它被视为用户意图的一部分,即用户应该决定哪个翻译单元(和目标文件)将包含每个定义.

In order to support this principle of independent translation, each entity with external linkage has to be defined in one translation unit, and in only one translation unit. The user is responsible for distributing such entities between different translation units. It is considered a part of user intent, i.e. the user is supposed to decide which translation unit (and object file) will contain each definition.

这同样适用于类的静态成员.类的静态成员是具有外部链接的实体.编译器希望您在某个翻译单元中定义该实体.此功能的全部目的是让您有机会选择那个翻译单元.编译器无法为您选择它.同样,这是您意图的一部分,您必须告诉编译器.

The same applies to static members of the class. Static members of the class are entities with external linkage. The compiler expects you to define that entity in some translation unit. The whole purpose of this feature is to give you the opportunity to choose that translation unit. The compiler cannot choose it for you. It is, again, a part of your intent, something you have to tell the compiler.

这不再像以前那样重要,因为该语言现在旨在处理(并消除)大量相同的定义(模板、内联函数等),但是 One Definition规则仍然植根于独立翻译的原则.

This is no longer as critical as it used to be a while ago, since the language is now designed to deal with (and eliminate) large amount of identical definitions (templates, inline functions, etc.), but the One Definition Rule is still rooted in the principle of independent translation.

除上述之外,在 C++ 语言中,您定义变量的点将决定其相对于同一翻译单元中定义的其他变量的初始化顺序.这也是用户意图的一部分,也就是说,如果没有您的帮助,编译器无法做出决定.

In addition to the above, in C++ language the point at which you define your variable will determine the order of its initialization with regard to other variables defined in the same translation unit. This is also a part of user intent, i.e. something the compiler cannot decide without your help.

从 C++17 开始,您可以将静态成员声明为 inline.这消除了对单独定义的需要.通过以这种方式声明它们,您可以有效地告诉编译器您不关心该成员的物理定义位置,因此也不关心它的初始化顺序.

Starting from C++17 you can declare your static members as inline. This eliminates the need for a separate definition. By declaring them in that fashion you effectively tell compiler that you don't care where this member is physically defined and, consequently, don't care about its initialization order.

相关文章