【浅拷贝】只是增加了一个指针,指向已存在对象的内存
    【深拷贝】是增加了一个指针,并新开辟了一块空间,让指针指向这块新开辟的空间。
    浅拷贝也叫位拷贝,拷贝的是地址。
    深拷贝也叫值拷贝,拷贝的是内容。
    深拷贝和浅拷贝可以简单理解为:如果一个类拥有资源,当这个类的对象发生复制过程的时候,资源重新分配,这个过程就是深拷贝,反之,没有重新分配资源,就是浅拷贝。
    【浅拷贝】多个对象共用同一块资源,同一块资源释放多次,崩溃或者内存泄漏

    实例讲解:默认拷贝构造函数,默认赋值构造函数,浅拷贝
    默认拷贝构造函数,默认赋值构造函数在拷贝过程中是按字节复制的,对于指针型成员变量只复制指针本身,而不复制指针所指向的目标,所以是浅拷贝。
    使用默认拷贝构造函数构造的多个对象共用同一块资源,同一块资源释放多次,崩溃或者内存泄漏。
    1、什么情况下会调用默认构造函数?
    一个对象以值传递的方式传入函数体
    一个对象以值传递的方式从函数返回
    一个对象需要通过另外一个对象进行初始化。
    浅拷贝:拷贝构造函数,赋值重载
    深拷贝:每个对象共同拥有自己的资源,必须显式提供拷贝构造函数和赋值运算符。

    1. #include <iostream>
    2. using namespace std;
    3. class Student
    4. {
    5. private:
    6. int num;
    7. char *name;
    8. public:
    9. Student();
    10. ~Student();
    11. };
    12. Student::Student() {
    13. name = new char(20);
    14. cout << "Student" << endl;
    15. }
    16. Student::~Student() {
    17. cout << "~Student " << (int)name << endl;
    18. delete name;
    19. name = NULL;
    20. }
    21. int main()
    22. {
    23. {// 花括号让s1和s2变成局部对象,方便测试
    24. Student s1;
    25. Student s2(s1);// 复制对象,使用默认构造函数
    26. }
    27. system("pause");
    28. return 0;
    29. }

    现象:调用一次构造函数,调用两次析构函数,两个对象的指针成员所指内存相同,这会导致什么问题呢?name指针被分配一次内存,但是程序结束时该内存却被释放了两次,会导致崩溃!
    原因:这是由于编译系统在我们没有自己定义拷贝构造函数时,会在拷贝对象时调用默认拷贝构造函数,进行的是浅拷贝!即对指针name拷贝后会出现两个指针指向同一个内存空间。
    解决方法:在对含有指针成员的对象进行拷贝时,必须要自己定义拷贝构造函数,使拷贝后的对象指针成员有自己的内存空间,即进行深拷贝,这样就避免了内存泄漏发生。也可使用std::shared_ptr解决内存泄漏问题。

    1. #include <iostream>
    2. using namespace std;
    3. class Student
    4. {
    5. private:
    6. int num;
    7. char *name;
    8. public:
    9. Student();
    10. ~Student();
    11. Student(const Student &s);//拷贝构造函数,const防止对象被改变
    12. };
    13. Student::Student()
    14. {
    15. name = new char(20);
    16. cout << "Student" << endl;
    17. }
    18. Student::~Student()
    19. {
    20. cout << "~Student " << (int)name << endl;
    21. delete name;
    22. name = NULL;
    23. }
    24. Student::Student(const Student &s)
    25. {
    26. name = new char(20);
    27. memcpy(name, s.name, strlen(s.name));
    28. cout << "copy Student" << endl;
    29. }
    30. int main()
    31. {
    32. {// 花括号让s1和s2变成局部对象,方便测试
    33. Student s1;
    34. Student s2(s1);// 复制对象
    35. }
    36. system("pause");
    37. return 0;

    调用一次构造函数,一次自定义拷贝构造函数,两次析构函数。两个对象的指针成员所指内存不同。
    默认赋值构造函数:

    1. String a(“hello”);
    2. String b(“world”);
    3. String c = a; // 调用了拷贝构造函数,最好写成 c(a);
    4. c = b; // 调用了赋值构造函数

    将对象 A 的内容复制到对象C;,这其中涉及到对象C 原有内容的丢弃,新内容的复制。 但”=”的缺省操作只是将成员变量的值相应复制。旧的值被自然丢弃。 由于对象内包含指针,将造成不良后果:指针的值被丢弃了,但指针指向的内容并未释放。指针的值被复制了,但指针所指内容并未复制。 因此,包含动态分配成员的类除提供拷贝构造函数外,还应该考虑重载”=”赋值操作符号。

    总结:
    浅拷贝只是对指针的拷贝,拷贝后两个指针指向同一个内存空间,深拷贝不但对指针进行拷贝,而且对指针指向的内容进行拷贝,经深拷贝后的指针是指向两个不同地址的指针。
    再说几句:
    当对象中存在指针成员时,除了在复制对象时需要考虑自定义拷贝构造函数,还应该考虑以下两种情形:
    1.当函数的参数为对象时,实参传递给形参的实际上是实参的一个拷贝对象,系统自动通过拷贝构造函数实现;
    2.当函数的返回值为一个对象时,该对象实际上是函数内对象的一个拷贝,用于返回函数调用处。
    3.浅拷贝带来问题的本质在于析构函数释放多次堆内存,使用std::shared_ptr,可以完美解决这个问题。