每个文件都有自己的静态变量副本吗?

时间:2011-09-15 20:02:50

标签: c++

假设头文件中有一个静态全局变量,并且在main.cpp中使用此变量。

// header.h
static int variableOne = 100;

//main.cpp
   .
   .
   cout << variableOne << endl;

main.cpp是否会获得自己的 variableOne 副本(尽管该值仍为100 ......)?或者我将这个概念与extern混合(我知道extern告诉编译器 variableOne 是在项目的其他地方定义的......)

谢谢。

5 个答案:

答案 0 :(得分:6)

如果您在头文件中声明static变量,则会在每个包含头文件的 translation unit 中创建该变量的副本。

所以从不在Header File中声明一个静态变量。

此外, C ++ 03标准:7.3.1.1/2 说:

  

在声明命名空间作用域中的对象时,不推荐使用static关键字    unnamed-namespace 提供了一个更好的选择。

C ++ 03标准:7.3.1.1/1 说:

  

“虽然未命名的命名空间中的实体可能具有外部链接,但它们实际上由其翻译单元唯一的名称限定,因此永远不会从任何其他翻译单元中看到。”

简单来说,unnamed namespace通过名称修改将其成员的可见性限制在翻译单元的范围内,并避免使用static关键字时遇到的问题。

此外,您不能在变量上同时使用关键字staticextern,因为两者都旨在实现互斥行为。

答案 1 :(得分:5)

在这种情况下,每个编译模块都将获得它自己的变量副本。

如果您使用extern,则只会有一个副本。但是你只能在一个模块中初始化它。

换句话说,如果您只是在示例中将static替换为extern,则它将无法编译,因为它正在包含该标头的每个模块中进行初始化。

答案 2 :(得分:4)

每个源文件都会获得variableOne的独立副本。

  

static的最后一次使用是作为代码文件中的全局变量。   在这种情况下,使用static表示其他的源代码   属于项目一部分的文件无法访问该变量。只要   单个文件中的代码可以看到变量。

<强> Source

如果使用extern,所有源文件都将引用相同的变量,但您无法在标头中初始化它。您必须为其中一个源文件添加初始化。

答案 3 :(得分:4)

1。是什么意思#include

当您编写#include "header.h"时,编译器基本上只是复制文件的整个内容而不是该行。在C ++中,头文件没有语义含义,它只用于文本替换。

所以,如果你有

---- header.h ----
static int variableOne = 100;

---- main.cpp ----
#include "header.h"

...
std::cout << variableOne << std::endl;
编译器的

完全相同
---- main.cpp ----
static int variableOne = 100;

...
std::cout << variableOne << std::endl;

2。在这种情况下,静态是什么意思

静态变量就像生命周期中的全局变量(即它在main开始之前构造并且在main终止之后被销毁)但仅在定义它的翻译单元内可见。因此,您可以在不同的翻译单元中使用相同的静态变量 name ,并且所有这些变量都是不同的(每个翻译单元将看到自己的静态变量)。

3。在标头中放置静态变量声明会发生什么?

最终结果是,包含该标题的每个翻译单元都将获得具有该名称的自己的静态变量,因为它与翻译单元在.cpp中定义静态变量而不是在{{1}}中的静态变量完全相同头文件。

所有这些名称都是相同的,但它们将是不同的变量。当然,如果头文件声明并初始化变量,则初始值将是相同的,但所有这些变量将是不同的,如果例如一个转换单元更改该变量,则更改将不会其他翻译单位看到。

答案 4 :(得分:3)

命名空间作用域中的

static变量不是外部的,因此您将获得项目中每个“转换单元”的静态变量的副本。自C ++ 03以来,这种技术已被废弃,推荐的方法现在将变量封装在一个未命名的命名空间中。