【发布时间】:2016-05-24 10:35:59
【问题描述】:
考虑以下代码sn-p:
#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;
}
全局命名空间和命名命名空间 N 被赋予外部链接,因为来自 N4567 的 3.5 [basic.link] 第 4 段说
未命名命名空间或在未命名命名空间中直接或间接声明的命名空间具有内部链接。 所有其他命名空间都有外部链接...
此外,::a 和 N::a 也被赋予了外部链接,因为它们不适用于 3.5 [basic.link] 第 3 段,
具有命名空间范围 (3.3.6) 的名称如果是以下名称,则具有内部链接
- 显式声明为静态的变量、函数或函数模板;或者,
- 非易失性 const 限定类型的变量,既没有显式声明为 extern,也没有先前声明为具有外部链接;或
- 匿名联合的数据成员。
但是到 3.5 [basic.link] 第 4 段,
...具有命名空间范围的名称上面没有给出内部链接,如果它是
的名称,则它与封闭的命名空间具有相同的链接
- 一个变量;或
- ...
这意味着它们继承了与全局命名空间和N相同的链接(=外部链接)。总之,它们应表示同一实体,因为 3.5 [basic.link] 第 9 段说
如果两个名称相同(第 3 条)并且在不同的范围内声明,则应表示相同的变量、函数、类型、枚举器、模板或命名空间
- 两个名称都有外部链接或两个名称都有内部链接并在同一个翻译单元中声明;和
- ...
但是,它们似乎表示不同的实体,因为它们的地址不一致。这是为什么呢?
【问题讨论】:
-
最后报价之后的那一行呢? (注意您引用的内容之后的 和。)
-
@Mat
::a和N::a肯定在一个翻译单元中声明。 -
但是 ::a 和 N::a 都在同一个全局范围内声明...您为什么希望第 9 段适用?
-
我说的是 §3.5/9,没有提到翻译单元
-
@JimLewis 他们不是在不同的范围内声明的吗?
::a在全局命名空间中声明,N::a在N中声明。
标签: c++ language-lawyer linkage