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

时间:2012-07-24 02:53:11

标签: c++ static namespaces

我有一个名称空间foo,其中包含一个整数bar,声明为......

foo.h中:

namespace foo {
    int bar;
}

现在,如果我只在一个文件中包含foo.h,那么这很好用。但是当我从两个或多个文件中包含foo.h时出现问题:我收到链接器错误。我发现如果我将bar声明为static,我可以将foo.h包含在多个文件中。这对我来说似乎很奇怪,因为我不知道可以在命名空间内声明一个静态变量。 (这甚至意味着什么?)

为什么这样做?更重要的是,为什么没有没有 static?在static中使用namespace时的含义是什么?

4 个答案:

答案 0 :(得分:38)

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

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

如果您想要一个变量,您应该在标题中将其声明为extern,并在一个翻译单元中提供单个定义。

答案 1 :(得分:26)

当您将变量声明为static时,表示其范围仅限于给定的翻译单元。没有static,范围是全局的。

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

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

答案 2 :(得分:4)

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

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

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

答案 3 :(得分:0)

还请注意,默认情况下,C ++的命名空间(全局)范围内的exports.A = class A { ... }; exports.b = 'constant'; 已隐式添加了const intDefine constant variables in C++ header

为了更好地了解发生了什么,请对编译的中间ELF目标文件执行static,您将清楚地看到符号是否定义了两次。这是一个详细的示例:What does "static" mean in C?