命名空间中的静态变量与非静态变量

Mic*_*rst 37 c++ static namespaces

我有一个foo包含整数的命名空间bar,声明如此...

foo.h中:

namespace foo {
    int bar;
}
Run Code Online (Sandbox Code Playgroud)

现在,如果我foo.h只包含一个文件,这就可以了.但是当我foo.h从两个或更多文件中包含时出现问题:我收到链接器错误.我想出如果我声明barstatic,我可以包含foo.h在多个文件中.这对我来说似乎很奇怪,因为我不知道可以在命名空间内声明一个静态变量.(那有什么意思?)

为什么这样做?更重要的是,为什么没有它的工作没有 staticstatic在用于什么时意味着什么namespace

Dav*_*eas 41

static在不同的背景下有多种含义.在这个特定的上下文中,它意味着变量具有内部链接,因此包含该标题的每个翻译单元将拥有它自己的变量副本.

请注意,虽然这会使链接器错误无声,但它会foo::bar为生成的每个目标文件维护一个单独的变量(更改将在不同的目标文件中不可见).

如果需要单个变量,则应将其声明为extern标题,并在一个转换单元中提供单个定义.


iam*_*ind 28

将变量声明为时static,表示其范围仅限于给定的转换单位.没有static范围是全球性的.

当您将变量声明为static.h文件内(在或不在内namespace;无关紧要),并将该头文件包含在各种.cpp文件中时,该static变量将成为每个.cpp文件的本地范围.
所以现在,包含该头的每个.cpp文件都有自己的变量副本.

如果没有static关键字,编译器将只生成该变量的一个副本,因此只要将头文件包含在多个.cpp文件中,链接器就会抱怨多个定义.

  • 谢谢@iammilind。我对预处理器对包含防护的作用的误解是问题所在。即使包含防护存在,代码也会被替换到*每个* testX.cpp 文件中一次(如果它是“#include”)。包含保护是为了保护同一文件中的双重定义。 (2认同)

bam*_*s53 6

该问题是由变量的多个定义引起的。不同翻译单元中的定义相互冲突,就像多个非内联函数定义不起作用一样。

当您将变量设为静态时,您将给变量内部链接,因此每个翻译单元都有自己独立的副本。

您可能真正想要的是仅将声明放在标题中(使用 extern),然后将定义放在实现文件中。