C++11标准给出了下面的代码片段(我删除了不相关的代码)并表示名称
i
具有外部链接。 (第 3.5.6 条)
static int i = 0; // #1
void g() {
extern int i; // #3 external linkage
}
他们为什么要这样做?我是不是误会了什么?这两个
i
在vs2012中指的是同一个对象。当我在其他地方使用 i
时,我遇到了未解决的外部错误。我不知道vs2012是否支持这个功能。
编辑: 我认为 VS2012 做的是正确的事情。 #3 中的
i
只需要引用具有链接的 i
即可。如果编译器找不到,则应在其他翻译单元中定义 i
。所以上面代码片段中的两个i
应该指的是同一个对象。
标准引用:
如果存在具有链接的实体的可见声明 相同的名称和类型,忽略最内层之外声明的实体 封闭命名空间范围,块范围声明声明 同一实体并接收先前声明的链接。如果 没有找到匹配的实体,块作用域实体接收外部 联动。
但是为什么人们需要这个功能?
#3
只是一个声明;它指出程序中某处存在一个名为 i
的变量,具有外部链接,但没有定义该变量。该声明允许您在 #1
的范围内使用它,而不是 g
中的静态变量。
您还需要在包含
g
的命名空间中定义它。在这种情况下,它必须位于不同的翻译单元中,这样它就不会与同名的静态变量冲突。
需要明确的是,这里有两个不同的变量,称为
i
,如示例后面的段落中所述。 #1
在这里定义; #3
只是声明,需要单独定义。
static int i = 0; // #1
void g() {
extern int i; // #3 external linkage
}
第一个
static
i
是一个声明,仅在当前源文件中可见。
extern int i;
告诉编译器我的意思不是这个
static i
,而是在其他地方定义的另一个i
。如果您尚未在其他地方(在另一个翻译单元中)定义它,您将获得未定义的引用。
这不会破坏 ODR,因为这个(
static
)i
是静态的(仅在本单元中可见)。
extern int i;
承诺编译器我会给你一个
int i
。
static int i=0;
不是承诺的变量,您必须在该 int i
变量声明可见的其他地方声明 extern
。
换句话说,
extern int i;
和static int i=0;
是两个不相关的变量。
程序的行为在最新的 C++ 标准 (c++23) 中发生了变化。
extern int i;
现在在 C++23 中具有 内部链接。特别是,给定的程序在 C++17 到 C++20 中是“格式错误”的,但在 C++23 中它是“格式正确的”,如下所述。在 C++11/14 中,extern int i;
具有外部链接,并且程序在 C++11/14 中格式良好。
C++23extern int i;
:
的内部链接[示例1:
static void f();
extern "C" void h();
static int i = 0; // #1
void q() {
extern void f(); // internal linkage
extern void g(); // ::g, external linkage
extern void h(); // C language linkage
int i; // #2: i has no linkage
{
extern void f(); // internal linkage
extern int i; // #3: internal linkage
}
}
即使第 #2 行的声明隐藏了第 #1 行的声明,第 #3 行的声明仍然重新声明 #1 并接收内部链接。—结束示例]