我对.cpp文件之间的变量访问如何工作有点模糊。例如:
int main()
{
int a = i;
return 0;
}
int i;
这会在main.cpp上生成编译器错误,告诉我i中没有。那么“静态”关键字在这种情况下有什么区别呢? (我尝试使用谷歌搜索,但大多数“静态关键字”信息页面谈论类和功能)
static int i;
它是一样的吗?是否会阻止extern int i
用于访问其他地方的i
?匿名命名空间的使用在如何处理变量方面有何不同?
namespace
{
int i;
}
总结一下:
答案 0 :(得分:2)
在您的第一个示例中,main2.cpp
定义了一个全局变量i
,如果main.cpp
声明extern
,则{em}可以访问 i
已出现在该文件中。 (通常,extern声明来自头文件。)您遇到编译器错误,因为i
中从未声明main.cpp
,这意味着编译器假定没有这样的变量。
在第二个示例中,main2.cpp
定义了文件范围变量i
。文件范围变量与全局变量不同,即使它们碰巧具有相同的名称。如果你在第二个例子中在i
中有main.cpp
的extern声明,那么两个文件都会成功编译,但是你会得到一个链接错误,因为没有< em> global 变量i
已定义。
如果您将main2.cpp
从第二个示例重命名为main3.cpp
,则将i
的外部声明添加到main.cpp
,编译所有三个并将它们全部链接在一起,成功; main.cpp和main2.cpp将共享一个名为i
的变量,而main3.cpp
将拥有自己的完全独立的变量,也称为i
。
这个东西叫做 linkage 。命名空间几乎完全与链接无关。但是,匿名命名空间是特殊的。在匿名命名空间中定义变量用于所有实际目的与使用static
定义变量相同 - 它使其成为文件范围变量。 (如果我没记错的话,那就有区别,但只有你使用导出的模板做复杂的事情才有意义,并且由于导出的模板使用得很少,以至于他们正在谈论从C ++标准中删除该功能,所以你不要我不得不担心它。)
匿名命名空间的值是您可以在其中放置类定义,这使得所有类的方法都是文件本地的。 (只有class { ... }
块必须在namespace { ... }
块内才能产生这种效果。)你不能以任何其他方式做到这一点。
答案 1 :(得分:1)
所有全局变量都有某种链接。需要extern
链接来在不同文件之间的不同上下文中命名相同的变量。
extern
是默认值。如果您在变量声明中实际使用extern
,则将其视为对另一个文件的引用。省略任何链接说明符以实际创建变量;这必须只在一个文件中发生。
extern int i; // i exists somewhere in some .cpp file.
int i; // ah! this is the file it exists in.
// (Although nothing special about that.)
应用于全局(命名空间范围)的 static
使其成为文件的本地。您从私有名称空间获得相同的效果,因此不推荐使用函数或类范围之外的static
。许多人仍然使用它。
static
规则的例外意味着文件本地在类和inline
函数中。类static
成员应该更恰当地称为extern
,因为语义是相同的。它很丑陋而令人困惑,但我想Bjarne只想将extern
作为关键字消除。
内联函数在多个.cpp
文件中可以具有相同的定义,因此当创建static
变量时,也会共享变量定义。
答案 2 :(得分:0)