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