C++ 可以在.h文件中声明静态全局变量吗?
static关键字将全局变量的范围限制在该转换单元内。 如果我在一个.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 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
extern
。相反,稍后将未定义的符号链接到一个定义,与饥饿的模板实例化相同。
const int x = ...;
#ifndef MYHEADER_H
#define MYHEADER_H
/* contents of header */
#endif