C++ 中的静态变量

Posted

技术标签:

【中文标题】C++ 中的静态变量【英文标题】:Static variables in C++ 【发布时间】:2011-04-11 12:20:27 【问题描述】:

我想知道头文件中的静态变量与类中声明的区别。在头文件中声明静态变量时,其范围仅限于 .h 文件或所有单元。当在类中声明时,通常静态变量在 .cpp 文件中初始化吗?那么这是否意味着静态变量范围仅限于 2 个编译单元?

【问题讨论】:

“静态”关键字非常重载。在不同的地方有不同的意思。这就是为什么在面试中提出一个有趣的问题。 绝对位居榜首,还有抽象函数/抽象类,以及诸如公共/受保护/私有继承之类的东西。 ;-) @vrdhn 一点也不好玩... 【参考方案1】:

对不起,我乱序回答你的问题,这样更容易理解。

在头文件中声明静态变量时,其范围仅限于 .h 文件或跨所有单元。

没有“头文件范围”这样的东西。头文件被包含到源文件中。翻译单元是源文件包括头文件中的文本。您在头文件中写入的任何内容都会复制到每个包含源文件中。

因此,在头文件中声明的静态变量就像每个单独的源文件中的静态变量。

由于以这种方式声明变量 static 意味着内部链接,因此每个翻译单元 #include 在您的头文件中都会获得其自己的个人变量(不是在您的翻译单元之外可见)。这通常不是您想要的。

我想知道头文件中的静态变量与类中声明的区别。

在类声明中,static 表示类的所有实例共享这个成员变量;即,您可能有数百个这种类型的对象,但只要其中一个对象引用static(或“类”)变量,所有对象的值都是相同的。您可以将其视为“全局类”。

当在类中声明时,通常静态变量在 .cpp 文件中初始化?

是的,one(并且只有one)翻译单元必须初始化类变量。

那么这是否意味着静态变量范围仅限于 2 个编译单元?

正如我所说:

标头不是编译单元, static 的含义完全不同,具体取决于上下文。

全局static 将范围限制为翻译单元。 static 类对所有实例都是全局的。

我希望这会有所帮助。

PS:检查 Chubsdad 回答的最后一段,关于在 C++ 中你不应该使用 static 来指示内部链接,而是使用匿名命名空间。 (因为他是对的。;-))

【讨论】:

“静态意味着完全不同的东西,具体取决于上下文。” --> 最令人困惑的根源。这种“不添加关键字”的心态真的很烦人:( @Matthieu M. 取决于您的立场。对于保持 C 和 C++ 之间的一些兼容性,这是非常有益的。不过,我承认他们用static 有点过火了。 我知道兼容性是必要的,否则该语言不会那么受欢迎。然而,他们可以使用新的关键字来表示 C++ 的含义,他们可以在类/结构范围之外将其设为“非关键字”以保持向后兼容性。我很高兴他们确实在 C++0x 中引入了 nullptr 关键字。 嗯...static 在类范围内的使用方式 有点类似于它在 function 范围内的使用方式(变量在多种用途)。他们确实介绍了一种方法来摆脱static(匿名命名空间)的另一种使用......总而言之,这项工作还不错。在任何情况下都比 Java 好。 :-D【参考方案2】:

头文件中的静态变量:

'common.h'

static int zzz;

这个变量'zzz' 有内部链接(这个变量不能在其他翻译单元中访问)。每个包含'common.h' 的翻译单元都有自己独特的名称对象'zzz'

类中的静态变量:

类中的静态变量不是该类的子对象的一部分。类的所有对象共享的静态数据成员只有一个副本。

$9.4.2/6 - "a 的静态数据成员 命名空间范围内的类具有外部 链接(3.5)。本地类不得 有静态数据成员。”

假设'myclass.h'

struct myclass
   static int zzz;        // this is only a declaration
;

myclass.cpp

#include "myclass.h"

int myclass::zzz = 0           // this is a definition, 
                               // should be done once and only once

"hisclass.cpp"

#include "myclass.h"

void f()myclass::zzz = 2;    // myclass::zzz is always the same in any 
                               // translation unit

"ourclass.cpp"

#include "myclass.h"
void g()myclass::zzz = 2;    // myclass::zzz is always the same in any 
                               // translation unit

因此,类静态成员不仅限于 2 个翻译单元。它们只需要在任一翻译单元中定义一次。

注意:使用“静态”来声明 文件范围变量已弃用,并且 未命名的命名空间是一个优越 备用

【讨论】:

“每个包含的文件”... 非常不准确,因为头文件可以包含其他头文件。最好坚持使用短语编译单元翻译单元 和 +1 指出匿名命名空间取代了全局变量的 static 修饰符。 @Ben Voight:是的,我会将其更改为翻译单元。旧习惯很难改掉...谢谢【参考方案3】:

在类外部的头文件中声明的静态变量在每个包含头文件的 .c 文件中都是 file-scoped。这意味着可以在包含头文件的每个 .c 文件中访问具有相同名称的变量的单独副本。

另一方面,静态类变量是class-scoped,每个编译单元都可以使用相同的静态变量,包括包含带有静态变量的类的标头。

【讨论】:

以上是关于C++ 中的静态变量的主要内容,如果未能解决你的问题,请参考以下文章

c++中关于私有静态变量的问题

C++类中的静态成员函数以及静态成员变量

C++类中的静态成员函数以及静态成员变量

C++中的全局变量普通局部变量和静态局部变量的区别

c++中静态成员变量和静态成员函数(笔试经历)

C++:OpenMP 中的私有静态变量