1.拷贝构造函数

1.1 拷贝构造函数定义

复制构造函数是构造函数的一种,也称拷贝构造函数,它只有一个参数,参数类型是本类的引用。

如果类的设计者不写复制构造函数,编译器就会自动生成复制构造函数。大多数情况下,其作用是实现从源对象到目标对象逐个字节的复制,即使得目标对象的每个成员变量都变得和源对象相等。编译器自动生成的复制构造函数称为“默认复制构造函数”。

注意:默认构造函数(即无参构造函数)不一定存在,但是复制构造函数总是会存在。

1.2 例子

#include <iostream>

class Text {
private:
    int m_x;
    int m_y;
public:
    Text() {                      默认构造函数
        m_x = 0;
        m_y = 0;
    }
    Text(int x,int y) {           带参数的构造函数
        m_x = x;
        m_y = y;
    }
    Text(const Text& another) {   显示默认复制构造函数
        m_x = another.m_x;
        m_y = another.m_y;
    }
    void PrintText() {
        std::cout << "x = " << m_x << ",y = " << m_y << std::endl;
    }
};
int main() {
    Text t1;
    t1.PrintText();

    Text t2(t1);                  会调用复制构造函数,将t1复制给t2
    t2.PrintText();
}
输出结果
x = 0,y = 0
x = 0,y = 0

特别的

实例化对象时
Text t2 = t1; 也是调用默认复制构造函数

但是
Text t2;
t2 = t1;       调用的不是复制构造函数

原因:构造函数是对象初始化的时候调用

​Text t2; ​​ 已经初始化完成,所以t2 = t1;​​调用的不是复制构造函数,而是t2的赋值操作符函数("="运算符的重载)

void operator=(const Text& another){
    m_x = another.m_x;
    m_y = another.m_y;
}

2.浅拷贝

2.1 浅拷贝定义

复制这个类的对象时,将复制其指针成员,但不复制指针指向的缓冲区,其结果是两个对象指向同一块动态分配的内存。销毁其中一个对象时,delete[]释放这个内存块,导致另一个对象存储的指针拷贝无效。这种复制被称为浅复制,会威胁程序的稳定性,

2.2 浅拷贝的例子

#include <iostream>

class Student {
private:
    int m_id;
    char *m_name;
public:
    Student(int id,const char *name) {
        std::cout << "调用Student(int id,char* name)……" << std::endl;

        m_id = id;
        m_name = (char*)malloc(strlen(name) + 1);  //在栈上创建
        //name = new char[strlen(name) + 1]; //在堆上创建
        strcpy_s(m_name,sizeof(name), name);
    }
    void PrintS() {
        std::cout << "ID = " << m_id << ", Name = " << m_name << std::endl;
    }
    ~Student() {   //析构函数
        std::cout << "调用~Student()……" << std::endl;
        if (m_name != NULL) {
            free(m_name);
            m_name = NULL;
        }
    }
};
int main() {
    Student s1(1,"huajian");
    s1.PrintS();

    Student s2(s1); //调用默认拷贝构造函数
    s2.PrintS();
    return 0;
}
运行结果
调用Student(int id,char* name)……
ID = 1, Name = huajian
ID = 1, Name = huajain
调用~Student()……
调用~Student()……

浅拷贝与深拷贝.exe (进程 28484)已退出,代码为 -805306369。

原因:

3. 深拷贝

3.1 深拷贝的定义

复制这个类的对象时,深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。

3.2 深拷贝的实现

显示的提供一个拷贝构造函数,来完成深拷贝动作

Student(const Student& another) {
    m_id = another.m_id;
    m_name = (char*)malloc(strlen(another.m_name) + 1);
    strcpy_s(m_name, sizeof(m_name), another.m_name);
}