ODR和内部链接
ODR and internal linkage
假设我在一个程序中有两个编译单元,每个编译单元都声明了一个非内联函数,具有相同的签名,但实现不同,例如
// a.cpp
namespace internal {
int foo(int a) {
return a+1;
}
}
int main() {
}
和
// b.cpp
namespace internal {
int foo(int b) {
return b+2;
}
}
Compiling/linking 这个(g++ 4.8.3 with -std=c++11
),我得到一个错误
b.cpp:(.text+0x0): multiple definition of `internal::foo(int)'
这是意料之中的,因为据我所知,这只是违反了 one definition rule:
One and only one definition of every non-inline function or variable
that is odr-used (see below) is required to appear in the entire
program (including any standard and user-defined libraries).
现在,将 namespace internal
更改为未命名的命名空间,错误消失了。直觉上,这对我来说很有意义,因为我正在改变函数 external to internal linkage:
Any of the following names declared at namespace scope have external
linkage unless the namespace is unnamed or is contained within an
unnamed namespace (since C++11): variables and functions not listed
above (that is, functions not declared static [...]) ...
和
[A]ll names declared in unnamed namespace or a namespace
within an unnamed namespace, even ones explicitly declared extern,
have internal linkage.
但是,我无法在一个定义规则中找到任何免除具有内部链接的函数的内容。因此,我的问题是:我的直觉推理是否正确,或者我是否仍然违反具有内部链接的函数的单一定义规则(并且 compiler/linker 只是不再报告)?另外,标准(或cppreference.com :)
)在哪里说是否可以?
n4713
§6.5 Program and linkage [basic.link]
A name is said to have linkage when it might denote the same object,
reference, function, type, template, namespace or value as a name
introduced by a declaration in another scope:
(2.1) — When a name has external linkage, the entity it denotes can be
referred to by names from scopes of other translation units or from
other scopes of the same translation unit.
(2.2) — When a name has internal linkage, the entity it denotes can
be referred to by names from other scopes in the same translation
unit.
— When a name has no linkage, the entity it denotes cannot be referred
to by names from other scopes.
这基本上是说(在未命名命名空间的情况下)来自 a.cpp
的名称 foo
和来自 b.cpp
的名称 foo
各自指代不同的实体。所以你没有同一个对象的两个定义,所以没有违反 ODR。
假设我在一个程序中有两个编译单元,每个编译单元都声明了一个非内联函数,具有相同的签名,但实现不同,例如
// a.cpp
namespace internal {
int foo(int a) {
return a+1;
}
}
int main() {
}
和
// b.cpp
namespace internal {
int foo(int b) {
return b+2;
}
}
Compiling/linking 这个(g++ 4.8.3 with -std=c++11
),我得到一个错误
b.cpp:(.text+0x0): multiple definition of `internal::foo(int)'
这是意料之中的,因为据我所知,这只是违反了 one definition rule:
One and only one definition of every non-inline function or variable that is odr-used (see below) is required to appear in the entire program (including any standard and user-defined libraries).
现在,将 namespace internal
更改为未命名的命名空间,错误消失了。直觉上,这对我来说很有意义,因为我正在改变函数 external to internal linkage:
Any of the following names declared at namespace scope have external linkage unless the namespace is unnamed or is contained within an unnamed namespace (since C++11): variables and functions not listed above (that is, functions not declared static [...]) ...
和
[A]ll names declared in unnamed namespace or a namespace within an unnamed namespace, even ones explicitly declared extern, have internal linkage.
但是,我无法在一个定义规则中找到任何免除具有内部链接的函数的内容。因此,我的问题是:我的直觉推理是否正确,或者我是否仍然违反具有内部链接的函数的单一定义规则(并且 compiler/linker 只是不再报告)?另外,标准(或cppreference.com :)
)在哪里说是否可以?
n4713
§6.5 Program and linkage [basic.link]
A name is said to have linkage when it might denote the same object, reference, function, type, template, namespace or value as a name introduced by a declaration in another scope:
(2.1) — When a name has external linkage, the entity it denotes can be referred to by names from scopes of other translation units or from other scopes of the same translation unit.
(2.2) — When a name has internal linkage, the entity it denotes can be referred to by names from other scopes in the same translation unit.
— When a name has no linkage, the entity it denotes cannot be referred to by names from other scopes.
这基本上是说(在未命名命名空间的情况下)来自 a.cpp
的名称 foo
和来自 b.cpp
的名称 foo
各自指代不同的实体。所以你没有同一个对象的两个定义,所以没有违反 ODR。