const引用是否在C ++中具有外部链接?

时间:2014-03-31 15:25:33

标签: c++ compiler-construction linker

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

  

具有命名空间作用域(3.3.5)的名称具有内部链接(如果它是

的名称)      
      
  • 明确声明为静态的对象,参考,函数或函数模板,

  •   
  • 显式声明为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;

可以编译。

3 个答案:

答案 0 :(得分:2)

引用本身不是const,只是它引用的对象;所以(可以说)这个规则并没有给出参考内部联系。

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

  

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

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

答案 1 :(得分:0)

我认为@Mike是正确的,这不是新事物,只是一点点提示。

有引用和引用的对象,对象可以是常量然后是内部链接,但引用本身永远不能是常量,因为它没有CV概念(引用在声明期间初始化,然后从不转移到某个对象否则,我记得GCC抱怨如果你提供一个常量引用,意味着int const& r = o;虽然VS没有抱怨,这没有意义),因为引用既不是常量也不是静态,那么声明跨越源文件

答案 2 :(得分:0)

这是一个具有最常量引用的程序。它编译并与C ++ 17(try it)链接:

// a.cpp

extern const int& ir;

int main() { return ir; }
// b.cpp

constexpr const int& ir = 42;

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

结论:全局引用变量具有外部链接,除非声明为static或在匿名名称空间中。同样,引用上的constexpr关键字不会使引用成为对引用者(try it)的不变看法。


并且constexpr引用不是隐式的inline。这是C ++ 17(try it)中ir的重新定义:

// a.cpp

constexpr const int& ir = 42;

int main() { return ir; }
// b.cpp

constexpr const int& ir = 42;

如果在两个文件中都将inline放在ir的声明之前,则会编译并链接(try it)。