编译器构造 - 常量引用在C++中是否具有外部链接

compiler construction - Does const reference have external linkage in C++?

本文关键字:是否 链接 外部 C++ 常量 引用 编译器      更新时间:2023-10-16

根据 1998 年标准第 3.5 节第 3 C++条,常量引用具有内部链接。

具有命名空间范围 (3.3.5) 的名称具有内部链接,如果它是

  • 显式声明为 static 的对象、引用、函数或函数模板,或者,

  • 明确声明
  • 为const的对象或引用,既未明确声明extern,也未先前声明具有外部链接;或

  • 匿名工会的数据成员。

但是为什么在编译下面的代码时会产生多个定义冲突呢?

// a.cpp
const int& a = 1;
int main()
{
    return 0;
}
// b.cpp
const int& a = 1;

然后编译代码。

$ g++ a.cpp b.cpp
/tmp/ccb5Qi0M.o:(.bss+0x0): multiple definition of `a'
/tmp/ccD9vrzP.o:(.bss+0x0): first defined here
collect2: error: ld returned 1 exit status

如果将 const 引用更改为 const,如下所示

// a.cpp
const int a = 1;
int main()
{
    return 0;
}
// b.cpp
const int a = 1;

编译是可以的。

引用本身不是const,只是它引用的对象; 所以(可以说)这个规则没有给引用内部链接。

引用声明为const是没有意义的。C++11标准澄清了措辞:

显式

声明constconstexpr且既未显式声明extern也未声明为具有外部链接的变量

没有提到const声明的引用的荒谬概念.

我认为@Mike是正确的,这里没有新东西,只是一点提示。

有引用和引用的对象,对象可以是常量然后是

内部链接,但引用本身永远不可能是常量,因为它没有 CV 概念(引用在声明期间初始化,然后永远不要转移到其他对象,我记得 GCC 抱怨如果你给出一个常量引用,意思是 int const&r = o; 虽然 VS 没有抱怨, 这毫无意义),因为引用既不是常量也不是静态的,那么声明会交叉源文件。

这是一个具有有史以来最常量引用的程序。它编译并与C++17链接(尝试一下):

// a.cpp
extern const int& ir;
int main() { return ir; }
// b.cpp
constexpr const int& ir = 42;

如您所见,ir可以从另一个翻译单元引用,即它具有外部链接。

结论:全局引用变量具有外部链接,除非声明为 static 或在匿名命名空间中。此外,引用上的constexpr关键字不会使引用成为引用对象的常量视图(尝试一下)。


并且constexpr引用不是隐式inline.这是对 C++17 中ir的重新定义(试试看):

// a.cpp
constexpr const int& ir = 42;
int main() { return ir; }
// b.cpp
constexpr const int& ir = 42;

如果在两个文件中将inline放在ir声明之前,它将编译并链接(尝试一下)。

相关文章: