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

Does each file get its own copy of the static variable?

本文关键字:变量 副本 静态 自己的 文件      更新时间:2023-10-16

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

// header.h
static int variableOne = 100;
//main.cpp
   .
   .
   cout << variableOne << endl;

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

谢谢。

如果你在头文件中声明了一个static变量,那么在每个翻译单元中,你包含了头文件,该变量的副本将被创建。

So 永远不要在头文件中声明静态变量

, c++ 03标准:7.3.1.1/2 说:

在命名空间范围内声明对象时,不建议使用static关键字unnamed-namespace提供了一个更好的选择。

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

"[a]尽管未命名名称空间中的实体可能具有外部链接,但它们有效地由其翻译单元的唯一名称限定,因此永远无法从任何其他翻译单元中看到。"

简而言之,unnamed namespace通过名称混淆将其成员的可见性限制在翻译单元的范围内,避免了使用static关键字时遇到的问题。

同样,你不能在一个变量上同时使用关键字staticextern,因为它们的目的是实现互斥行为。

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

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

换句话说,如果你只是用extern替换static在你的例子中,它不会编译,因为它是初始化的每个模块,包括该头。

#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。在这个上下文中,static是什么意思

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

3。在头文件中声明静态变量会发生什么?

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

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

每个源文件将获得自己独立的variableOne副本。

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

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

名称空间范围内的static变量不是外部的,因此您将为项目中的每个'翻译单元'获得静态变量的副本。自c++ 03以来,这种技术已经过时了,现在推荐的方法是将变量包含在未命名的名称空间中。