【问题标题】:Does const reference have external linkage in C++?const 引用在 C++ 中是否有外部链接?
【发布时间】:2014-03-31 15:25:33
【问题描述】:

根据 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;

编译就OK了。

【问题讨论】:

    标签: c++ compiler-construction linker


    【解决方案1】:

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

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

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

    没有提及声明 const 的无意义的引用概念。

    【讨论】:

    • 您的意思是 C++ 1998 标准中的措辞具有误导性?
    • @spockwang:我不知道“误导”,但它确实令人困惑,现在已经澄清了。
    • 有没有人有一个很好的例子来使用这样的引用,并且希望它默认不是文件范围的?
    • @MikeSeymour 引用不是 C++11 标准中的变量吗?
    • @spockwang:是的。但是不能显式声明const,所以这条规则不适用于它。
    【解决方案2】:

    我认为@Mike 是正确的,这里没有什么新鲜事,只是一点提示。

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

    【讨论】:

      【解决方案3】:

      这是一个具有const 引用次数最多的程序。它编译并与 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)。

      【讨论】:

        猜你喜欢
        • 2017-03-12
        • 2015-01-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多