C++ 可以在.h文件中声明静态全局变量吗?

C++ 可以在.h文件中声明静态全局变量吗?,c++,c,static,global,extern,C++,C,Static,Global,Extern,static关键字将全局变量的范围限制在该转换单元内。 如果我在一个.h文件中使用static int x,并每隔一个文件包含一个.h文件,它们不都属于同一个翻译单元吗? 那么,x不是随处可见吗? 那么现在静态的角色是什么呢 另外,如果x是一个全局变量,是否使用了静态常量int x? 默认情况下,不是所有常量全局变量都是静态的吗? 常量变量的作用域是否仅限于TU,即使它被限制在文件中的for循环中?每次翻译都会得到该变量的私有副本,如果将其放在那里,将导致膨胀。也没有必要到处乱拷贝。不,不好 您

static关键字将全局变量的范围限制在该转换单元内。 如果我在一个.h文件中使用
static int x
,并每隔一个文件包含一个.h文件,它们不都属于同一个翻译单元吗? 那么,x不是随处可见吗? 那么现在静态的角色是什么呢

另外,如果x是一个全局变量,是否使用了静态常量int x? 默认情况下,不是所有常量全局变量都是静态的吗?
常量变量的作用域是否仅限于TU,即使它被限制在文件中的for循环中?

每次翻译都会得到该变量的私有副本,如果将其放在那里,将导致膨胀。也没有必要到处乱拷贝。不,不好


您可以在
命名空间
块中声明
常量int
;没关系。

基本上,每个源文件以及所有包含的头文件都是一个翻译单元。因此,如果头文件中有一个静态变量,那么它在包含头文件的每个源文件(翻译单元)中都是唯一的

如果我在一个.h文件中使用static int x,并且每个 其他文件,它们不都属于同一个翻译单位吗

如果将某个对象声明为静态(不在类内,因为class static关键字具有不同的语义),则无法在其TU之外看到该静态变量。因此,将其放入头文件将导致每个TU(包括该头文件)都具有该静态变量的不同私有副本

常量变量的作用域是否仅限于TU(即使它被限制) 在文件中的for循环中

不可以。即使对于静态常量值,范围也由其声明确定。因此,范围将受到括号的限制。

如果您编写

static const int x
在.h文件中,包含-s this.h的每个翻译单元都有自己的私有变量
x

如果您想让每个人都能看到1个全局变量,您应该编写

extern const int x;
在.h文件和

在其中一个.cpp文件中


如果您想让一个静态常量只对一个翻译单元可见,请不要在.h文件中提及它。

对于
常量
合格的变量,可观察到的差异是,在
静态
版本中,每个翻译单元将有一个副本,因此可以对两个副本进行比较失败

如果从不使用
const
变量的地址,任何现代编译器都应该能够使用该值并优化变量本身。在这种情况下,
静态
常量
-限定变量是完全正确的。

静态全局变量没有意义,它们在某种程度上是相互对立的

术语“全局”经常被误用来描述在文件范围内的任何函数之外声明的变量。但是,全局变量是具有外部链接的变量,可以被项目中的任何文件访问,因此是全局变量

外部链接的反面是内部链接,这意味着变量只能由声明它的转换单元访问。翻译单元,指一个
.c
文件及其包含的所有标题(递归)

static
是变量获得内部链接的保证。因此,其他翻译将无法访问它或声明引用它的
extern
变量

如果在头文件中声明一个
静态
变量,则多个翻译单元将获得一个具有该名称的单独变量。虽然聪明的链接器会注意到这一点并给出一个链接器错误,但代码可以很好地编译。这类链接器错误通常是非描述性的,很难追踪

这使我们得出以下最佳做法:

  • 永远不要在头文件中声明任何变量,因为这通常会产生微妙的bug和链接器错误
  • 为防止此类错误,请始终使用“标题保护”围绕所有标题文件:

  • 所有在文件范围内声明的变量都应该声明为静态的,以实现私有封装和减少命名空间混乱。类似地,应该避免使用
    extern
    ,因为它会导致糟糕的设计和意大利面编程


我发现在标题中最常用的静态方法是引入bug,或者使调试变得更困难。但是每个标题都有一个围栏,如果没有,应该只包含一次?这是一个单独的问题(我从来没有为设计为包含多次的标题设置种子)。即使你有#ifndef fences,你仍然需要考虑你是否需要
extern
。相反,稍后将未定义的符号链接到一个定义,与饥饿的模板实例化相同。
const int x = ...;
#ifndef MYHEADER_H 
#define MYHEADER_H 
  /* contents of header */ 
#endif