ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

深拷贝与浅拷贝

2022-03-28 18:34:42  阅读:157  来源: 互联网

标签:释放 函数 默认 Person 拷贝 构造函数


 

深拷贝与浅拷贝 

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

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

 

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;
}

 

结果:

 

标签:释放,函数,默认,Person,拷贝,构造函数
来源: https://www.cnblogs.com/anjingdian/p/16068450.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有