• 深拷贝与浅拷贝 安静点


    深拷贝与浅拷贝 

    浅拷贝:简单的赋值拷贝操作,或者说编译器自己生成的默认拷贝函数

    深拷贝:在堆区重新申请空间,进行拷贝操作

    class Person {
    public:
        //无参(默认)构造函数
        Person() {
            cout << "无参构造函数!" << endl;
        }
        //有参构造函数
        Person(int age, int height) {
    
            cout << "有参构造函数!" << endl;
    
            m_age = age;
            //因为new是在堆区存储数据,所以用一个指针接收返回数据
            m_height = new int(height);
    
        }
     
    
        //析构函数 专门释放堆区数据的
        ~Person() {
            cout << "析构函数!" << endl;
            if (m_height != NULL)
            {
                //释放在堆区中的数据。
                delete m_height;
                //防止野指针出现,设置成空指针。
                m_height = NULL;
            }
        }
    public:
        int m_age;
        int* m_height;
    };
    
    void test01()
    {
        Person p1(18, 180);
    
        cout << "p1的年龄: " << p1.m_age << " 身高: " << *p1.m_height << endl;
    
        Person p2(p1);
         
        cout << "p2的年龄: " << p2.m_age << " 身高: " << *p2.m_height << endl;
    }
    
    int main() {
    
        test01();
    
        system("pause");
    
        return 0;
    }

    当前代码运行起来之后会报错:

    因为在有参构造函数中创建了一个堆区的数据,在执行Person p2(p1)的时候编译器默认的拷贝函数也会简单的在栈上存储height的地址,当离开test01这个函数体的时候自动调用析构函数,栈上的数据是先进后出(因为test01函数中没有new,数据在栈上),所以先释放p2的数据,这里的析构函数是自己写的,可以看到释放了m_height在堆上的数据,当在释放p1(注意p1上的m_height存储的是堆地址,此时它是有值的,不会因为p2释放了导致它在栈上的值没有了)的时候又会重新释放,根据栈上的地址找堆,发现找不到了,导致重复释放报错。

    上述就是因为编译器默认的浅拷贝造成的,如果属性有在堆区开辟的,一定要自己提供拷贝构造函数,防止浅拷贝带来的问题

    自己创建拷贝函数解决:

    class Person {
    public:
        //无参(默认)构造函数
        Person() {
            cout << "无参构造函数!" << endl;
        }
        //有参构造函数
        Person(int age, int height) {
    
            cout << "有参构造函数!" << endl;
    
            m_age = age;
            //因为new是在堆区存储数据,所以用一个指针接收返回数据
            m_height = new int(height);
    
        }
        //拷贝构造函数  
        Person(const Person& p) {
            cout << "拷贝构造函数!" << endl;
            //如果不利用深拷贝在堆区创建新内存,会导致浅拷贝带来的重复释放堆区问题
            m_age = p.m_age;
            //这样不论调用多少次拷贝函数,前后的m_height中存储的堆地址都不是一样的了
            m_height = new int(*p.m_height);
    
        }
    
        //析构函数 专门释放堆区数据的
        ~Person() {
            cout << "析构函数!" << endl;
            if (m_height != NULL)
            {
                //释放在堆区中的数据。
                delete m_height;
                //防止野指针出现,设置成空指针。
                m_height = NULL;
            }
        }
    public:
        int m_age;
        int* m_height;
    };
    
    void test01()
    {
        Person p1(18, 180);
    
        cout << "p1的年龄: " << p1.m_age << " 身高: " << *p1.m_height << endl;
    
        Person p2(p1);
         
        cout << "p2的年龄: " << p2.m_age << " 身高: " << *p2.m_height << endl;
    }
    
    int main() {
    
        test01();
    
        system("pause");
    
        return 0;
    }

    结果:

  • 相关阅读:
    css学习记录(css元素类型)
    一个面向对象的js问题 大家帮忙看看
    css选择器记录
    css学习记录
    如何进行高效JavaScript单元测试
    js拖动库介绍
    PHP 方法记录
    jquery学习笔记(一)
    windows8 后台传递下载
    .NET Framework 4.5 RC 更新
  • 原文地址:https://www.cnblogs.com/anjingdian/p/16068450.html
Copyright © 2020-2023  润新知