引用由T以外的类型的值初始化的const T.

时间:2014-03-02 14:32:35

标签: c++ visual-c++ c++11 g++ clang++

以下代码:

struct A {
    explicit A(int) {}
};

const A& a(1);    // error on g++/clang++/vc++
const A& b = 1;   // error on g++/clang++/vc++
const A& c{1};    // ok on g++/clang++, error on vc++
const A& d = {1}; // error on g++/clang++/vc++

4初始化中的哪一个是合法的?

如果我们首先忽略vc ++,那么direct-init和copy-init之间的区别似乎并不一致。如果第三个是格式良好的,因为它是direct-init,为什么第一个也是direct-init的第一个无法编译?这背后的逻辑是什么?或者它只是g ++ / clang ++的一个错误,vc ++正确处理它?<​​/ p>

2 个答案:

答案 0 :(得分:5)

如果您正在使用 braced-init-lists ,并且初始化的目标类型是引用:

[dcl.init.list] / 3(来自n3690)

  
      
  • 否则,如果初始化列表包含E类型的单个元素,并且T不是引用类型或其引用类型是   与E相关的引用,对象或引用从中初始化   那个元素;如果要求缩小转换(见下文)   将元素转换为T,程序格式不正确。

  •   
  • 否则,如果T是引用类型,则T引用的类型的prvalue临时值是copy-list-initialized或   direct-list-initialized,取决于初始化的类型   引用,引用绑定到临时。 [注意: As   通常情况下,绑定将失败,程序是不正确的,如果   reference类型是对非const类型的左值引用。 - 结束记录]

  •   
  • 否则,如果初始化列表没有元素,则对象进行值初始化。

  •   

对于两个示例const A& c{1};const A& d = {1};,上述引文的第二个子弹适用。第一个是直接列表 - 初始化const A,第二个是复制列表 - 初始化const A。选择explicit构造函数的复制初始化格式不正确,请参阅[over.match.list] / 1.


如果您没有使用braced-init-lists,那么就我所知,复制初始化和直接初始化之间没有区别。 [dcl.init.ref] / 5的最后一个子弹适用于所有情况:

  
      
  • 否则,将创建一个临时类型为“ cv1 T1”并从初始化表达式初始化   使用非参考拷贝初始化的规则(8.5)。然后将引用绑定到   暂时的。
  •   

复制初始化无法选择explicit ctor,请参阅[over.match.copy] / 1(它不可行)。


结论:

const A& c{1};

是合法的。另一个不是,因为他们要么使用复制初始化,要么使用复制列表初始化,唯一可行/选择的ctor是explicit

答案 1 :(得分:0)

您的结构只能通过显式调用它的构造函数来创建。不允许隐式转换。

const引用必须指向构造中该类型的现有对象。

你的所有行都没有通过调用它的显式构造函数来创建类型A的对象。所以我不明白为什么这些行应该正确初始化const引用。