c++ - ODR和内部链接

标签 c++ c++11 linkage one-definition-rule

假设我在一个程序中有两个编译单元,每个编译单元都声明了一个非内联函数,具有相同的签名,但实现不同,例如

// 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 :

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.

但是,我无法在一个定义规则中找到任何免除具有内部链接的函数的内容。因此,我的问题是:我的直觉推理是否正确,或者我是否仍然违反具有内部链接的函数的单一定义规则(并且编译器/链接器不再报告它)?此外,标准(或 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 和来自 的名称 foo >b.cpp 分别引用不同的实体。所以您没有同一对象的两个定义,因此不违反 ODR。

关于c++ - ODR和内部链接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55266022/

相关文章:

c++ - 穿过院子而不被淋湿

c++ - boost shared_ptr 使用默认构造函数

c++ - 可选地支持模板的 initializer_list 构造可能包装容器

c++ - 标准库 stdio.h 重载函数的第二个 C 链接

c++ - 使用 extern 的前向声明(在 C/C++ 的上下文中)

c++ - 如何禁止在 C++ 2011 中调用右值对象的 const 成员函数?

c++ - std::move on std::string 是否保证 .c_str() 返回相同的结果?

c++ - 我如何在 Mac 上构建 gcc?

c++ - __LINE__ 在传递给类似函数的宏的 lambda 中计算不一致

c++ - 是否将 namespace 范围的文件本地 (.cpp) 常量放置在匿名 namespace 中