C++学习之路(五):复制构造函数与赋值运算符重载

时间:2021-07-04 19:25:36

之前没有细想过两者的区别,今天对此进行简要记录,后续完善补充。

复制构造函数是在类对象被创建时调用的,但是赋值运算符是被已经存在的对象调用完成赋值操作。

复制构造函数只在对象实例化时才被调用,即在复制构造函数调用期间,这个对象处于未决状态(直到复制构造函数被成功调用),另外复制构造函数没有返回值。

赋值运算符则是在一个现存对象被赋予新的值时才被调用,并且它有返回值(可以返回类对象,也可以返回类对象引用)

举个例子:

class A
{
public:
    A()
    {
        cout<<"class create"<<endl;
    }
    A(const A &a)
    {
        cout<<"class copy"<<endl;
    }
    A &operator=(const A &a)
    {
        cout<<"override ="<<endl;
        return *this;
    }
};

int main()
{
    //1
    A x;

    //2
    A y(x);

    //3
    A z;
    z = y;

    //4
    A w = x;

    return 0;
}

给出输出结果,再进行分析:

C++学习之路(五):复制构造函数与赋值运算符重载

1:定义类对象x,调用构造函数,输出class create

2:将类对象x复制给y,y是一个待进行实例化的对象,这里调用复制构造函数,输出class copy

3:定义类对象z,调用构造函数,输出class create,然后将y复制给z,这里z已经是一个现存的对象,这里调用赋值运算符重载。输出override =

4:属于隐式类转换,调用复制构造函数实例化类对象w,输出class copy。一般情况下,抑制隐式转换,可以采用explicit关键字。

 

上述赋值运算符重载函数返回类型为引用,如果返回类型为对象即 A operator=(const A &a),则会由于生成一个临时对象作为返回值复制给z,从而调用复制构造函数,并在返回后调用析构函数删除临时对象。测试如下:

class A
{
public:
    A()
    {
        cout<<"class create"<<endl;
    }
    A(const A &a)
    {
        cout<<"class copy"<<endl;
    }
    A operator=(const A &a)  //返回对象
    {
        cout<<"override ="<<endl;
        return *this;
    }
    ~A()
    {
        cout<<"class delete"<<endl;
    }
};

int main()
{
    //1
    A x;

    //2
    A y(x);

    //3
    A z;
    z = y;   //返回临时对象复制给z,不是返回的对象y的引用。

    //4
    A w = x;

    return 0;
}

结果如下:

C++学习之路(五):复制构造函数与赋值运算符重载