繁体   English   中英

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;
    }
}

编译/链接这个(g++ 4.8.3 with -std=c++11 ),我得到一个错误

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

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

odr 使用的每个非内联函数或变量(见下文)的一个且仅一个定义需要出现在整个程序(包括任何标准和用户定义的库)中。

现在,将namespace internal命名空间更改为未命名的命名空间,错误消失了。 直觉上,这对我来说很有意义,因为我正在将函数从外部链接更改为内部链接

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

[A] 在未命名命名空间或未命名命名空间内的命名空间中声明的所有名称,即使是明确声明为 extern 的名称,也具有内部链接。

但是,我无法在一个定义规则中找到任何可以免除具有内部链接的函数的内容。 因此,我的问题是:我的直觉推理是否正确,或者我是否仍然违反具有内部链接的函数的一个定义规则(并且编译器/链接器不再报告它)? 此外,标准(或 cppreference.com :) )在哪里说明它是否可以?

n4713

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

当一个名称可能表示与另一个作​​用域中的声明引入的名称相同的对象、引用、函数、类型、模板、命名空间或值时,就说它具有链接:

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

(2.2)——当一个名字有内部链接时,它所表示的实体可以被同一翻译单元中其他作用域的名字引用。

— 当名称没有链接时,它所表示的实体不能被其他范围的名称引用。

这基本上说,(在未命名空间的情况下)的名称fooa.cpp和名foob.cpp分别是指不同的实体。 所以你没有同一个对象的两个定义,所以不违反 ODR。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM