如果未生成复制构造函数,则在从已存在的对象初始化时使用哪个构造函数

Tie*_*ars 2 c++ constructor

我的代码如下:

class X {
public:
    explicit X(int x):m_x(new int{x}) {
        cout << "------------------------------------\n";
        cout << "Constuctor X(int x)"<<endl;
        cout << this << endl;

    }

    X() {
        cout << "------------------------------------\n";
        cout << "Constuctor X()"<<endl;
        cout << this << endl;
    }

    ~X() {
        cout << "------------------------------------\n";
        cout << "Destructor"<<endl;
        cout << this << endl;
    }

    int* m_x = nullptr;
    const int c_x = 10;
};

int main() {
  X x1;
  X x2{x1};
}
Run Code Online (Sandbox Code Playgroud)

和输出:

------------------------------------
Constuctor X()
0x7ffc22667cb0
------------------------------------
Destructor
0x7ffc22667cc0
------------------------------------
Destructor
0x7ffc22667cb0
Run Code Online (Sandbox Code Playgroud)

问题是:当我定义构造函数 X() 和 X(int x) 时,不再生成所有其他构造函数,那么在初始化对象 x2 时使用哪个构造函数?

Chr*_*ris 8

创建了默认的复制构造函数。

\n

如果您不想创建它请添加:

\n
X(const X& x) = delete;\n
Run Code Online (Sandbox Code Playgroud)\n

编译它会产生:

\n
test.cpp: In function \xe2\x80\x98int main()\xe2\x80\x99:\ntest.cpp:34:10: error: use of deleted function \xe2\x80\x98X::X(const X&)\xe2\x80\x99\n   X x2{x1};\n          ^\n
Run Code Online (Sandbox Code Playgroud)\n

考虑到对于具有原始指针成员的类来说使用默认的复制构造函数是一个坏主意,因为它只会复制指针而不复制它指向的数据。建议阅读:三/五/零规则

\n

在您的示例中,如果删除x1.m_x,x2.m_x则无效。

\n
class X {\npublic:\n    explicit X(int x):m_x(new int{x}) {\n        cout << "Constuctor X(int x)"<<endl;\n    }\n\n    X() {\n        cout << "Constuctor X()"<<endl;\n    }\n\n    ~X() {\n        cout << "Destructor"<<endl;\n    }\n\n    int* m_x = nullptr;\n    const int c_x = 10;\n};\n\nint main() {\n  X x1(23);\n  X x2{x1};\n\n  delete x1.m_x;\n\n  cout << *x.m_x << endl;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

在我的机器上运行:

\n
class X {\npublic:\n    explicit X(int x):m_x(new int{x}) {\n        cout << "Constuctor X(int x)"<<endl;\n    }\n\n    X() {\n        cout << "Constuctor X()"<<endl;\n    }\n\n    ~X() {\n        cout << "Destructor"<<endl;\n    }\n\n    int* m_x = nullptr;\n    const int c_x = 10;\n};\n\nint main() {\n  X x1(23);\n  X x2{x1};\n\n  delete x1.m_x;\n\n  cout << *x.m_x << endl;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

此类的自定义复制构造函数如下所示,其中实例现在拥有自己的数据来m_x指向。

\n
    X(const X& x) : m_x(new int{*x.m_x}), c_x(x.c_x) { }\n
Run Code Online (Sandbox Code Playgroud)\n

此外,移动构造函数将如下所示,没有新的内存分配,但m_x将成员x设置为nullptr。该实例X无法再修改数据m_x点。

\n
    X(X&& x) : m_x(x.m_x) : c_x(x.c_x) {\n        x.m_x = nullptr;\n    }\n
Run Code Online (Sandbox Code Playgroud)\n