请考虑以下两个类:
class B
{
public:
B() { }
B(const B& b) = delete; //Move ctor not implicitly declared
};
class A
{
public:
A() { }
operator B()
{
return B();
}
};
我可以看到为什么此代码可以正常编译:
A a;
B b = a;
遵循copy-initialization的规则,对象“ a”被转换为类型B的prvalue,并且由于在C ++ 17中不再需要复制构造函数,因此没有错误:
如果T是一个类类型,并且该类型的cv不合格版本 other不是T或不是从T派生的,或者T不是非类类型,而是 其他类型是一个类类型,用户定义的转换序列 可以将other的类型转换为T(或转换为T的类型 如果T是一个类类型并且有转换函数可用)是 检查并通过过载解析选择最佳的。的 转换的结果,是prvalue临时值(直到 C ++ 17)prvalue表达式(自C ++ 17起),如果转换构造函数是 使用,然后用于直接初始化对象。最后一步是 通常进行优化,然后构造转换结果 直接在分配给目标对象的内存中 需要适当的构造函数(移动或复制)才能访问 即使不使用它。 (直到C ++ 17)
但是为什么直接列表初始化也要编译?
A a;
B b{ a };
在list-initialization中找不到任何措辞说明在这种情况下编译器应尝试将A转换为B。仅考虑构造函数的重载解析:
如果上一阶段未产生匹配项,则T的所有构造函数 参与针对一组参数的重载解析 由braced-init-list的元素组成,但有限制 只允许非缩小的转换
但是在这种情况下,复制构造函数被删除了,所以不应该通过重载分辨率选择它吗?