c++ - 复制构造函数是否仍然参与复制初始化?

标签 c++ c++17 copy-constructor copy-initialization

考虑以下代码:

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&)声明为explicitX(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/

相关文章:

c++ - C++ 中继承的重载规则

c++ - 将新创建的对象传递给函数时是否可以避免复制构造函数?

c++ - 如何在基类 vector 中返回派生对象的拷贝?

c++ - 对象的分离构造和克隆

c++ - 堆调试 : Assert failure in dbgdel in MS VC++ 2005

C++ - 在模板类之外但在头文件中定义成员函数

c++ - 使用类似 auto 的东西进行初始化

c++ - 为什么使用 string_view 而不是广义的 container_view<T>?

c++ - g++ Bash For Windows 和 Ubuntu 的区别

c++ - 用户提供的 std::allocator 特化