可以在.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 ,因为它会导致糟糕的设计和意大利面条编程。