可以在.h文件中声明静态全局变量吗?
static关键字将全局变量的范围限制为该转换单元。 如果我在.h文件中使用static int x
并且每隔一个文件包含该.h文件,它们是否都属于同一个翻译单元? 那么,到处都不会看到x吗? 那么静态的作用是什么?
另外,有没有使用static const int x
,其中x是一个全局变量? 默认情况下,并非所有const全局变量都是静态的 并且const变量的范围仅限于TU,即使它被限制在文件中的for循环中?
如果你写
static const int x
在.h文件中,然后#include -s这个.h的每个翻译单元都有自己的私有变量x
。
如果你想让一个全局变量对你应该写的每个人都可见
extern const int x;
在.h文件中
const int x = ...;
在其中一个.cpp文件中。
如果你想让静态const int只对一个翻译单元可见 – 根本不要在.h文件中提及它。
如果我在.h文件中使用静态int x并且每隔一个文件包含该.h文件,它们是否都属于同一个翻译单元?
如果将某些东西声明为静态(不在类中,对于类static关键字具有不同的语义),则不能在其TU之外看到该静态变量。 因此将它放在头文件中将导致包含该头的每个TU具有该静态变量的不同私有副本。
并且const变量的范围仅限于TU,即使它被限制在文件中的for循环中?
没有。 即使对于静态const值,范围也由它的声明决定。 所以范围将受到括号的限制。
你最终将翻译每个翻译的私人副本,如果你把它放在那里会导致膨胀。 在整个地方随机复制也没有任何意义。 不,不行。
你可以在namespace
块中声明一个const int
; 没关系。
const
限定变量的可观察差异是,在static
版本中,每个翻译单元将获得一个副本,因此两个此类副本的地址比较可能会失败。
如果你从不使用const
变量的地址,任何现代编译器应该只能使用该值并自行优化变量。 在这种情况下, static
const
-qualified变量是完全正确的。
基本上,每个源文件以及所有包含的头文件都是单个翻译单元。 因此,如果头文件中有静态变量,那么在每个源文件(转换单元)中都将包含头文件。
“静态全球”没有意义,它们在某种程度上是彼此的对立面。
术语“全局”经常被误用来描述在文件范围内的任何函数外声明的变量。 相反,全局变量是具有外部链接的变量,可以由项目中的任何文件访问 – 因此是全局变量。
外部链接的反面是内部链接 ,这意味着变量只能由声明它的翻译单元访问。 翻译单元意味着一个.c
文件和它包含的所有标题(递归)。
static
是变量获取内部链接的保证。 因此,其他翻译将无法访问它或声明引用它的extern
变量。
如果在头文件中声明static
变量会发生多个转换单元将获得具有该名称的单独变量,会发生什么。 代码将编译正常,虽然聪明的链接器会注意到这一点并给出链接器错误。 这些链接器错误通常是非描述性的,很难追踪。
这引出了以下最佳实践:
- 永远不要在头文件中声明任何变量,因为这通常会产生细微的错误和链接器错误。
-
要防止此类错误,请始终使用“标题保护”包围所有标头文件:
#ifndef MYHEADER_H #define MYHEADER_H /* contents of header */ #endif
-
在文件范围内声明的所有变量都应声明为
static
,以便进行私有封装并减少名称空间混乱。 同样,应避免使用extern
,因为它会导致糟糕的设计和意大利面条编程。