【发布时间】:2019-08-11 10:58:40
【问题描述】:
假设我在一个程序中有两个编译单元,每个编译单元都声明了一个签名相同但实现不同的非内联函数,例如
// a.cpp
namespace internal {
int foo(int a) {
return a+1;
}
}
int main() {
}
和
// b.cpp
namespace internal {
int foo(int b) {
return b+2;
}
}
编译/链接这个(g++ 4.8.3 with -std=c++11),我得到一个错误
b.cpp:(.text+0x0): multiple definition of `internal::foo(int)'
这是意料之中的,因为据我所知,这只是违反one definition rule:
每个非内联函数或变量的一个且只有一个定义 odr-used(见下文)必须出现在整个 程序(包括任何标准和用户定义的库)。
现在,将 namespace internal 更改为未命名的命名空间,错误就消失了。直观地说,这对我来说很有意义,因为我正在从 external to internal linkage 更改函数:
在命名空间范围内声明的以下任何名称都具有外部 除非命名空间未命名或包含在 未命名的命名空间 (C++11 起):未列出的变量和函数 上面(即未声明为静态的函数 [...])...
和
[A]在未命名的命名空间或命名空间中声明的所有名称 在一个未命名的命名空间中,即使是显式声明的外部命名空间, 有内部联系。
但是,我无法在一个定义规则中找到任何内容,该规则将具有内部链接的函数排除在外。因此,我的问题是:我的直觉推理是否正确,还是我仍然违反具有内部链接的函数的单一定义规则(并且编译器/链接器不再报告它)?此外,标准(或 cppreference.com :))在哪里说明它是否可以?
【问题讨论】:
-
你的直觉是对的。从标准中寻找细节只会加强它。如果您从事语言律师,这是一个很好的目标。
标签: c++ c++11 linkage one-definition-rule