以下代码:
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>
答案 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引用。