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

时间:2012-08-15 10:11:25

标签: c++ c static global extern

static关键字将全局变量的范围限制为该转换单元。 如果我在.h文件中使用static int x并在每个其他文件中包含该.h文件,它们是否都属于同一个翻译单元? 那么,到处都不会出现x吗? 那么现在静态的作用是什么?

此外,是否有static const int x的使用,其中x是全局变量? 默认情况下,并非所有const全局变量都是静态的 并且const变量的范围仅限于TU,即使它被限制在文件中的for循环中吗?

6 个答案:

答案 0 :(得分:35)

如果你写

static const int x

.h 文件中, #include -s this .h 的每个翻译单元都有自己的私有变量{{1 }}

如果您希望每个人都能看到1个全局变量,那么您应该编写

x
.h 文件中的

extern const int x;

在其中一个 .cpp 文件中。

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

答案 1 :(得分:6)

  

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

如果将某些东西声明为静态(不在类中,对于类static关键字具有不同的语义),则不能在其TU之外看到该静态变量。因此将它放在头文件中将导致包含该头的每个TU具有该静态变量的不同私有副本。

  

并且const变量的范围仅限于TU,即使它受限制   在文件中的for循环中?

NO。即使对于静态const值,范围也由它的声明决定。所以范围将受到括号的限制。

答案 2 :(得分:3)

每次翻译时你最终会得到该变量的私有副本,如果你把它放在那里会导致膨胀。在整个地方随机复制也没有任何意义。不,不行。

您可以在const int块中声明namespace;没关系。

答案 3 :(得分:1)

const限定变量的可观察差异在于static版本,每个翻译单元将获得一个副本,因此两个此类副本的地址比较可能会失败。

如果你从不使用const变量的地址,任何现代编译器都应该能够使用该值并优化变量本身。在这种情况下,static const - 限定变量完全没问题。

答案 4 :(得分:0)

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

答案 5 :(得分:0)

“静态全局”没有意义,它们在某种程度上是彼此相反的。

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

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

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

如果您在头文件中声明一个static变量,将会发生不止一个转换单元使用该名称的单独变量的情况。该代码可以很好地编译,尽管聪明的链接器会注意到这一点并给出链接器错误。这些链接器错误通常是非描述性的,很难跟踪。

这使我们获得以下最佳实践:

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

    #ifndef MYHEADER_H 
    #define MYHEADER_H 
      /* contents of header */ 
    #endif
    
  • 在文件范围内声明的所有变量都应声明为static,以进行私有封装并减少命名空间的混乱。同样,应避免使用extern,因为它会导致不良的设计和意大利面条式的编程。