C++ 复制构造函数和重载 = 运算符的情况

C++ Copy Constructor and cases of Overloadin the = operator

在下面的代码中 d = a; 没有调用复制构造函数。

a 是如何复制到 d 的?或者在什么情况下我们必须重载=运算符?

#include<iostream>
using namespace std;

class code{    
    int id;

    public:    
    code(){}//default constructor

    code(int a){
            id=a;
    }

    code(code & x){//copy constructor
        id=x.id;
    }

    void display(){
        cout<<id;
    }
};

int main(){


    code a(100);
    code b(a);//copy constructor is called
    code c=a;//copy constructor is called again
    code d;
    c=a;//copy constructor is not called this time

    std::cout << "\n id of A: ";
    a.display();
    cout << "\n id of B: ";
    b.display();
    cout << "\n id of C: ";
    c.display();
    cout << "\n id of D: ";
    d.display();
    return 0;
}

如何有效地实现复制构造函数?

没有调用复制构造函数,因为调用了隐式定义的复制赋值运算符。它的形式是:

T& T::operator=(const T&)

初始化时可以调用拷贝构造函数:

code d = a;

在您的代码中:

code d;
d = a;

正在调用 operator=

How The a is copied to d ?

使用复制赋值运算符。复制构造函数用于初始化,而不是赋值。

In what cases we have to Overload the = operator ?

当您需要不同于递归复制每个子对象的默认行为时。在您的情况下,默认行为是简单地复制 id 值。这也是复制构造函数的默认行为,因此您也不需要提供它。

Rule of Three 是您何时需要提供这些运算符的良好指南。当您的 class 管理另一个资源的生命周期时,您通常需要它们,该资源在其析构函数中释放。您需要非标准的复制语义,这样您就不会得到两个对象试图释放相同的资源。

根据 C++ 标准(12.8 复制和移动 class 个对象)

18 如果 class 定义没有显式声明复制赋值运算符,则隐式声明一个。如果 class 定义声明了移动构造函数或移动赋值运算符,则隐式声明的复制赋值运算符被定义为已删除;否则,它被定义为默认 (8.4)。如果 class 具有用户声明的复制构造函数或用户声明的析构函数,则不推荐使用后一种情况。 class X 的隐式声明的复制赋值运算符将具有

形式

28 非联合 class X 的隐式定义 copy/move 赋值运算符对其子对象 执行成员 copy-/move 赋值。

在此声明中

c=a;

使用编译器复制赋值运算符隐式定义,因为 class 没有显式定义它,它执行对象数据成员的成员复制(对于这个 class 定义它是数据成员 int id;)

当对象子对象的成员方式复制不满足class要求时,您需要显式定义复制赋值运算符。