ODR和内部链接

ODR and internal linkage

本文关键字:链接 内部 ODR      更新时间:2023-10-16

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

// 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与-std=c++11),我有一个错误

b.cpp:(.text+0x0): multiple definition of `internal::foo(int)'

这是相当预期的,据我所知,这只是对一个定义规则的违反:

每个非内部功能或变量的一个定义 这是使用ODR(见下文)必须出现在整个 程序(包括任何标准和用户定义的库)。

现在,将namespace internal更改为未命名的名称空间,错误会消失。直观地,这对我来说很有意义,因为我正在将功能从外部链接更改为内部链接:

在名称空间范围上声明的以下任何名称都具有外部 链接,除非命名空间未命名或包含在 未命名的名称空间(自C 11):变量和功能未列出 上面(即,函数未声明为静态[...])...

[a] ll名称在未命名的名称空间或名称空间中声明 在一个未命名的名称空间中,即使是明确宣布为外部的空间, 具有内部联系。

但是,我在一个定义规则中找不到任何用内部链接豁免函数的任何内容。因此,我的问题是:我的直观推理是否正确,还是我仍在具有内部链接的函数(以及编译器/链接器不再报告)的一个定义规则?此外,标准(或cppreference.com :))在哪里说是可以的?

n4713

§6.5程序和链接[basic.link]

据说一个名称在可能表示同一对象时具有链接, 参考,功能,类型,模板,名称空间或值为名称 由另一个范围内的声明引入:

(2.1) - 当名称具有外部链接时,它表示的实体可以是 由其他翻译单元的范围或来自 同一翻译单元的其他范围。

(2.2) - 当名称具有内部链接时,它表示可以 在同一翻译中以其他范围的名称提及 单位。

- 当名称没有链接时,它表示的实体不能被转介 通过其他范围的名称。

这基本上说(在未命名的名称空间的情况下)a.cpp的名称foob.cpp中的名称foo每个都参考不同的实体。因此,您没有对同一对象的两个定义,因此不违反ODR。