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++ 中的静态变量的主要内容,如果未能解决你的问题,请参考以下文章