考虑以下代码:
class Y {};
class X
{
public:
X() { }
X(const Y&) { }
explicit X(const X&) { }
};
X f()
{
return X();
}
int main()
{
Y y;
X x = y;
f();
}
代码在 cannot convert from 'X' to 'X'
行给出错误 ( return X();
) 。据我了解,这是因为X(X const&)
声明为explicit
和X(X const&)
隐式“调用”以从 X()
创建的对象复制初始化返回的对象。由于存在复制省略,X()
当X(const X&)
时将用于直接创建返回的对象不是explicit
。然而,explicit
即使 X(X const&)
关键字也会停止代码不会真正被调用,所以我的猜测是 explicit
关键字不关心是否存在复制省略。
根据我的理解,复制初始化的形式如 X x = y;
首先会尝试转换y
输入X
,然后复制 X
类型的对象转换自 y
进入x
(因此 X x = y;
会执行类似 X x{ X{y} }
的操作),并且由于存在复制省略,因此 X
类型的对象转换自 y
将直接构造为x
.
然后,我注释掉函数 f()
的定义和调用。我预计同样的错误发生在 return X();
碰巧X x = y
,因为如果 X x = y
做类似 X x{ X{y} }
的事情,它会隐式调用 explicit X(const X&)
如果没有复制省略,根据我上面的猜测 explicit
关键字不应该关心是否存在复制省略。
但是这次没有编译错误。所以,我猜X x = y
不会打电话X(const X&)
即使没有复制省略。我猜X x = y
只是 X(const Y&)
的隐式调用.
请问我的猜测是否正确?如果没有,有人可以告诉我哪里出错了,为什么explicit X(const X&)
不影响X x = y;
当它停止时return X();
?
最佳答案
您的代码在较新的 C++17 中编译,因为强制复制省略不会检查可访问的复制/移动构造函数。
如果删除函数定义,则无论 C++ 版本如何,代码都有效,因为在 X x = y;
中,x
是从临时 直接初始化的code>X
(即复制构造函数被“显式”调用,因此 explicit
就可以了)。在 C++17 及更高版本中,这里首先没有临时的 X
。
关于c++ - 复制构造函数是否仍然参与复制初始化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72506263/