美文网首页
C++笔记:拷贝构造函数和赋值运算符重载

C++笔记:拷贝构造函数和赋值运算符重载

作者: 大凡呀 | 来源:发表于2019-03-24 17:01 被阅读0次

拷贝构造函数和赋值运算符重载

拷贝构造函数

对于普通类型的对象来说,它们之间的复制是很简单的,例如:

int a=88;
int b=a;

而对于类对象的拷贝,则相对复杂,请看下面的例子:

#include <iostream>
using namespace std;

class copyDemoClass {
public:
    copyDemoClass(int i):_i_ptr(new int(i)) {
        cout << "Construct..." << endl;
    }
    ~copyDemoClass() { delete _i_ptr; }
    void displayValue() const {
        cout << "Value is " << *_i_ptr << endl;
    }

private:
    int* _i_ptr;
};

int main(int agrc, char* argv[]) {
    copyDemoClass demo_class1(1);
    demo_class1.displayValue();

    copyDemoClass demo_class2(demo_class1);
    demo_class2.displayValue();

    return 0;
}

执行上述代码后结果如下:


double free

出现double free的结果是因为用demo_class1拷贝demo_class2,在程序员没有实现拷贝构造函数的情况下会进行按位拷贝。demo_class1demo_class2的“_i_ptr”成员变量会指向同一块内存,在main函数执行完成之后分别对两个类对象进行析构,就会对这块内存进行两次释放。上述的拷贝方式被称为“浅拷贝”。
出现上述问题的最佳解决方法是程序员自己实现一个拷贝构造函数来完成“深拷贝”。请看下述代码:

#include <iostream>
using namespace std;

class copyDemoClass {
public:
    copyDemoClass(int i):_i_ptr(new int(i)) {
        cout << "Construct..." << endl;
    }
    copyDemoClass(const copyDemoClass& other):_i_ptr(new int(*other._i_ptr)) {
        cout << "Copy Construct..." << endl;
    }
    ~copyDemoClass() { delete _i_ptr; }
    void displayValue() const {
        cout << "Value is " << *_i_ptr << endl;
    }

private:
    int* _i_ptr;
};

int main(int agrc, char* argv[]) {
    copyDemoClass demo_class1(1);
    demo_class1.displayValue();

    copyDemoClass demo_class2(demo_class1);
    demo_class2.displayValue();

    return 0;
}

上述代码第7行实现了一个拷贝构造函数,在执行copyDemoClass demo_class2(demo_class1) 时会调用该拷贝构造函数,会为demo_class2_i_ptr 成员分配一段新的内存,在执行析构函数时会释放该段内存,而不是释放demo_class1的成员变量指向的地址,不会造成二次释放。该段代码执行结果如下:

增加了拷贝构造函数

对此建议对于有复制意义的类必须显式地给出复制构造函数。

赋值运算符重载

对于有复制赋值意义的类,除了拷贝构造函数外,还需要手动重载赋值运算符。请看如下代码:

#include <iostream>
using namespace std;

class copyDemoClass {
public:
    copyDemoClass(int i):_i_ptr(new int(i)) {
        cout << "Construct..." << endl;
    }
    copyDemoClass(const copyDemoClass& other):_i_ptr(new int(*other._i_ptr)) {
        cout << "Copy Construct..." << endl;
    }
    ~copyDemoClass() { delete _i_ptr; }
    void displayValue() const {
        cout << "Value is " << *_i_ptr << endl;
    }

private:
    int* _i_ptr;
};

int main(int agrc, char* argv[]) {
    copyDemoClass demo_class1(1);
    demo_class1.displayValue();

    copyDemoClass demo_class2(-1);
    demo_class2 = demo_class1;
    demo_class2.displayValue();

    return 0;
}

执行上述代码后结果如下:


double free

发现熟悉的double free又出现了,但这时我们已经实现了拷贝构造函数,为什么还会出现double free的现象呢?
在上述代码中,首先会用参数-1作为demo_class2的构造函数参数,在demo_class2构造完成之后才调用的‘=’操作符,而此时demo_class2已经构造完成,所以不会调用任何构造函数(包括拷贝构造函数),而是调用编译器生成的默认的赋值运算符,而默认的赋值运算符是进行按位赋值的浅拷贝操作,所以在调用析构函数的时候demo_class的指针成员变量会进行两次释放的操作。
将上述代码修改如下:

#include <iostream>
using namespace std;

class copyDemoClass {
public:
    copyDemoClass(int i):_i_ptr(new int(i)) {
        cout << "Construct..." << endl;
    }
    copyDemoClass(const copyDemoClass& other):_i_ptr(new int(*other._i_ptr)) {
        cout << "Copy Construct..." << endl;
    }
    copyDemoClass& operator=(const copyDemoClass& other) {
        cout << "Assign Operator..." << endl;
        if(this == &other) {
            return *this;
        }
        _i_ptr = new int(*other._i_ptr);
        return *this;
    }
    ~copyDemoClass() { delete _i_ptr; }
    void displayValue() const {
        cout << "Value is " << *_i_ptr << endl;
    }

private:
    int* _i_ptr;
};

int main(int agrc, char* argv[]) {
    copyDemoClass demo_class1(1);
    demo_class1.displayValue();

    copyDemoClass demo_class2(-1);
    demo_class2 = demo_class1;
    demo_class2.displayValue();

    return 0;
}

上述代码执行结果如下:


赋值运算符重载

相关文章

  • 全面梳理 C++ 拷贝构造与赋值运算符重载(operator=)

    本文全面梳理 C++ 的拷贝构造与赋值运算符重载(operator=) 默认拷贝构造函数和赋值运算符 在默认情况下...

  • 1.2.18_C++ 赋值运算符重载

    C++ 重载运算符和重载函数 就像其他运算符一样,您可以重载赋值运算符( = ),用于创建一个对象,比如拷贝构造函...

  • c++第三讲 类和对象

    目标: 类的默认成员函数 构造函数 析构函数 拷贝构造函数 赋值操作符重载 默认拷贝函数与赋值运算符重载 cons...

  • c++11 拷贝控制

    拷贝控制操作包括,拷贝构造函数,拷贝赋值运算符,移动构造函数,移动赋值运算符,析构函数。拷贝和移动构造函数定义了用...

  • C++拷贝构造函数和拷贝赋值运算符问题

    为什么需要析构函数就几乎需要拷贝构造函数和拷贝赋值运算符?或者说拷贝构造函数和拷贝赋值运算符什么时候需要自己构造?...

  • C++笔记:拷贝构造函数和赋值运算符重载

    拷贝构造函数和赋值运算符重载 拷贝构造函数 对于普通类型的对象来说,它们之间的复制是很简单的,例如: 而对于类对象...

  • 2023-01-18 C++实现string类

    实现string类,用于学习 拷贝构造函数/拷贝赋值运算符/移动构造函数/移动赋值运算符

  • c++学习笔记2(GeekBand)

    拷贝构造、拷贝赋值和析构 c++中有Big Three三个特殊的函数,他们就是拷贝构造函数,拷贝赋值函数和析构函数...

  • 9.18学习总结

    今天学了继承和派生。 派生类:继承了基类的除了构造函数、析构函数、拷贝构造函数和赋值运算符重载函数之外的所有成员,...

  • 9月18日四期C++总结

    今天上午老师给我们讲解了继承和派生 派生类继承了基类的除了构造函数、析构函数、拷贝构造函数和赋值运算符重载函数之外...

网友评论

      本文标题:C++笔记:拷贝构造函数和赋值运算符重载

      本文链接:https://www.haomeiwen.com/subject/wriuvqtx.html