深拷贝与浅拷贝(C++)

区别

浅拷贝:简单的赋值拷贝
深拷贝:在堆区申请新的空间进行拷贝


示例

为方便理解,引入一段错误代码

#include <iostream>
#include <cstring>
using namespace std;

class Person
{
public:
    Person()
    {
        cout << "Person的默认构造函数调用" << endl;
    }
    Person(int age,int height)
    {
        pAge = age;
        pHeight  = new int(height);//堆区
        cout << "Person的有参构造函数调用" << endl;
    }
    ~Person()
    {
        //析构代码主要用于释放堆区数据
        if (pHeight != NULL)
        {
            delete pHeight;
            pHeight = NULL;
        }
        cout << "Person的析构函数调用" << endl;
    }
    int pAge;
    int *pHeight;
};

void test()
{
    Person p1(18,160);
    cout << "p1的年龄为:" << p1.pAge << endl;
    cout << "p1的身高为:" << *p1.pHeight << endl;

    //如果p2利用编译器提供的拷贝构造函数,会做浅拷贝操作(逐字节拷贝)
    Person p2(p1);//默认的拷贝构造,为浅拷贝
    cout << "p2的年龄为:" << p2.pAge << endl;
    cout << "p2的身高为:" << *p2.pHeight << endl;
}
int main()
{
    test();
    system("pause");
}

上述代码可正常通过编译,但实际运行后会提示以下错误

输出结果为

可以看到虽然原对象没有拷贝构造函数,但p2依然可以正确输出结果,但执行p2的析构函数时程序报错,因此只有p1的析构函数调用输出

原理

如果原对象没有拷贝构造函数,编译器会自动生成浅拷贝操作,源码为:

Person(const Person &p)
{
    //默认拷贝构造函数
    pAge = p.pAge;
    pHeight = p.pHeight;
}

不难理解,编译器做的就是把源对象内的成员值简单复制了过来
这会导致p2内的堆区成员与p1同源,也即是指向同一块堆区地址(pAge为局部变量,储存在栈区,由编译器自动分配释放)
如果在test函数中输出一下p1.pHeightp2.pHeight就会发现值是相同的

当test函数结束时,编译器会做两件事:

  1. 销毁p1,调用析构函数将堆区p1.pHeight释放
  2. 销毁p2,调用析构函数将堆区p2.pHeight释放

因为p2中pHeight与p1指向同一块堆区地址,当p1将此地址释放后,p2重复释放,导致程序程序报错

解决办法

为避免重复释放导致程序报错,就要使用深拷贝操作,可以手动定义Person的拷贝构造函数:

Person(const Person &p)
{
    cout << "Person的拷贝构造函数调用" << endl;
    pAge = p.pAge;
    pHeight = int new (*p.pHeight);//为pHeight开辟另一块堆区地址
}

此时p2将会为pHeight重新申请堆区空间,只是值与p1相同
如果输出p1.pHeight与p2.pHeight就会发现两者地址不同

图示

为方便理解,另附两张图
浅拷贝:

深拷贝:

本文作者:小小黑
本文链接:https://lonelyenderman.top/archives/248
版权声明:本站采用 BY-NC-SA 进行许可。转载请注明出处!

评论

  1. 空城
    Windows Chrome
    2年前
    2022-3-11 22:52:11

    您就是卷王王中王

    来自陕西

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(*^▽^*)
 ̄﹃ ̄
(╯‵□′)╯︵┴─┴
(~ ̄▽ ̄)~
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
( ͡° ͜ʖ ͡°)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
つ﹏⊂
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
(´▽`ʃ♡ƪ)
w(゚Д゚)w
(๑•̀ㅂ•́)و✧
(#`O′)
凸(艹皿艹 )
o(≧口≦)o
≡ω≡
(*/ω\*)
○| ̄|_
(⊙ˍ⊙)
Σ(っ °Д °;)っ
o( ̄ヘ ̄o#)
<( ̄︶ ̄)>
(。・∀・)ノ゙
(o゜▽゜)o☆
╥﹏╥
ヾ(´・ω・`)ノ
😂
😀
😅
😊
🙂
😍
😘
😜
😝
😏
😒
🙄
😳
😔
😫
😱
😭
😶
🌚
😣
🤨
😣
🤐
😪
🤤
🥵
🤮
😨
😱
😓
🤬
👴
🤡
🙈
💊
🙏
🤺
💩
👻
🙌
🖕
👍
👫
👌
🙏
👀
🐒
🔪
Source: github.com/zhheo/Sticker-Heo
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
Heo
花!
上一篇
下一篇