【发布时间】:2022-07-06 12:42:24
【问题描述】:
考虑以下代码:
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();
}
代码在return X(); 行出现错误(cannot convert from 'X' to 'X')。在我的理解中,这是因为X(X const&) 被声明为explicit 并且X(X const&) 被隐式“调用”以从X() 创建的对象中复制初始化返回的对象。由于存在复制省略,当X(const X&) 不是explicit 时,将直接使用X() 创建返回的对象。但是,explicit 关键字会停止代码,即使 X(X const&) 不会真正被调用,所以我的猜测是 explicit 关键字不关心是否存在复制省略。
在我的理解中,像X x = y; 这样的形式的复制初始化会首先尝试将y 转换为X 类型,然后将X 类型的对象从y 转换为x (所以X x = y; 做了类似X x{ X{y} } 的事情),并且由于存在复制省略,从y 转换而来的X 类型的对象将直接构造为x。
然后,我注释掉函数f()的定义和调用。我期待return X(); 发生同样的错误发生在X x = y,因为如果X x = y 执行类似X x{ X{y} } 的操作,如果没有复制省略,它会隐式调用explicit X(const X&),并且根据我对@ 的猜测987654352@关键字不关心是否有复制省略。
但是这次没有编译错误。所以,我猜X x = y 不会调用X(const X&),即使没有复制省略。我猜X x = y 只是对X(const Y&) 的隐式调用。
请问我的猜测是否正确?如果没有,有人可以告诉我哪里出错了,为什么explicit X(const X&) 在停止return X(); 时不会影响X x = y;?
【问题讨论】:
-
主要编译器(clang、gcc、msvc)似乎都在编译代码,只要您使用适当版本的标准 (>=17) 进行编译:godbolt.org/z/f3neav6Ps
标签: c++ c++17 copy-constructor copy-initialization