假设头文件中有一个静态全局变量,并且在main.cpp中使用此变量。
// header.h
static int variableOne = 100;
//main.cpp
.
.
cout << variableOne << endl;
main.cpp是否会获得自己的 variableOne 副本(尽管该值仍为100 ......)?或者我将这个概念与extern混合(我知道extern告诉编译器 variableOne 是在项目的其他地方定义的......)
谢谢。
答案 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
关键字时遇到的问题。
此外,您不能在变量上同时使用关键字static
和extern
,因为两者都旨在实现互斥行为。
答案 1 :(得分:5)
在这种情况下,每个编译模块都将获得它自己的变量副本。
如果您使用extern
,则只会有一个副本。但是你只能在一个模块中初始化它。
换句话说,如果您只是在示例中将static
替换为extern
,则它将无法编译,因为它正在包含该标头的每个模块中进行初始化。
答案 2 :(得分:4)
每个源文件都会获得variableOne
的独立副本。
static的最后一次使用是作为代码文件中的全局变量。 在这种情况下,使用static表示其他的源代码 属于项目一部分的文件无法访问该变量。只要 单个文件中的代码可以看到变量。
<强> Source 强>
如果使用extern
,所有源文件都将引用相同的变量,但您无法在标头中初始化它。您必须为其中一个源文件添加初始化。
答案 3 :(得分:4)
当您编写#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;
静态变量就像生命周期中的全局变量(即它在main
开始之前构造并且在main
终止之后被销毁)但仅在定义它的翻译单元内可见。因此,您可以在不同的翻译单元中使用相同的静态变量 name ,并且所有这些变量都是不同的(每个翻译单元将看到自己的静态变量)。
最终结果是,包含该标题的每个翻译单元都将获得具有该名称的自己的静态变量,因为它与翻译单元在.cpp
中定义静态变量而不是在{{1}}中的静态变量完全相同头文件。
所有这些名称都是相同的,但它们将是不同的变量。当然,如果头文件声明并初始化变量,则初始值将是相同的,但所有这些变量将是不同的,如果例如一个转换单元更改该变量,则更改将不会其他翻译单位看到。
答案 4 :(得分:3)
static
变量不是外部的,因此您将获得项目中每个“转换单元”的静态变量的副本。自C ++ 03以来,这种技术已被废弃,推荐的方法现在将变量封装在一个未命名的命名空间中。