为什么这些具有外部链接的名称不表示同一实体?

b1s*_*sub 1 c++ linkage language-lawyer

考虑以下代码片段:

#include <iostream>

int a;
void address_of_a(void) {
    std::cout << &a << std::endl;
}

namespace N {
    int a;
    void address_of_a(void) {
        std::cout << &a << std::endl;
    }   
};

int main(void) {
    address_of_a();
    N::address_of_a();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

全局命名空间和命名命名空间N被赋予外部链接,因为N4567的 3.5 [basic.link] 第 4 段说

未命名的命名空间或在未命名的命名空间内直接或间接声明的命名空间具有内部链接。所有其他命名空间都有外部链接...

此外,::aN::a也被给予外部链接,因为它们不适用于 3.5 [basic.link] 第 3 段,

具有命名空间范围 (3.3.6) 的名称具有内部链接,如果它是

  • 显式声明为静态的变量、函数或函数模板;或者,
  • 非易失性 const 限定类型的变量,既没有显式声明为 extern,也没有事先声明为具有外部链接;或者
  • 匿名联合体的数据成员。

但对于 3.5 [basic.link] 第 4 段,

...具有命名空间范围且未在上面给出内部链接的名称,如果它是以下名称,则与封闭命名空间具有相同的链接

  • 一个变量; 或者
  • ...

这意味着它们继承了与全局命名空间和N. 总之,它们应表示同一实体,因为 3.5 [basic.link] 第 9 段指出

相同的(第 3 条)并且在不同作用域中声明的两个名称应表示相同的变量、函数、类型、枚举数、模板或命名空间,如果

  • 两个名称都具有外部链接,或者两个名称都具有内部链接并且在同一翻译单元中声明;和
  • ...

然而,它们似乎表示不同的实体,因为它们的地址不一致。这是为什么?

cpp*_*ner 5

请参阅第二个项目符号。

相同的(第 3 条)并且在不同作用域中声明的两个名称应表示相同的变量、函数、类型、枚举数、模板或命名空间,如果

  • 两个名称都具有外部链接,或者两个名称都具有内部链接并且在同一翻译单元中声明;

  • 两个名称都引用同一名称空间的成员或同一类的非继承成员;和

  • 当两个名称都表示函数时,函数的参数类型列表(8.3.5)相同;和

  • 当两个名称都表示函数模板时,签名 (14.5.6.1) 相同。

::a并且N::a不引用相同命名空间的成员,因此它们不表示相同的变量。