C++知识点12:深拷贝浅拷贝

C++(笔记)深浅拷贝and何时调用

一、何时调用拷贝函数

  • 何时会调用拷贝函数?
    1、对象在创建时使用其他的对象初始化
    Person p(q); //此时复制构造函数被用来创建实例p
    Person p = q; //此时复制构造函数被用来在定义实例p时初始化p

2、对象作为函数的参数进行值传递时

f(p); //此时p作为函数的参数进行值传递,p入栈时会调用复制构造函数创建一个局部对象,与函数内的局部变量具有相同的作用域

需要注意的是,赋值并不会调用复制构造函数,赋值只是赋值运算符(重载)在起作用

p = q; //此时没有复制构造函数的调用! (记住初始化和赋值的区别)

简单来记的话就是,如果对象在声明的同时将另一个已存在的对象赋给它,就会调用复制构造函数;如果对象已经存在,然后将另一个已存在的对象赋给它,调用的就是赋值运算符(重载)


二、深浅拷贝解析

1、两者区别

1.在未定义显示拷贝构造函数的情况下,系统会调用默认的拷贝函数–即浅拷贝,它能够完成成员的一对一拷贝(逐位复制),当类中数据成员没有指针时,利用浅拷贝完全没问题的;但当数据成员中有指针时,如果采用简单的浅拷贝,那么两个类中的两个指针将会指向同一块地址,当对象快结束时,会调用两次析构器,从而导致指针悬挂现象,所以此时必须使用深拷贝
2.简单来说,带指针用深拷贝,不带指针用浅拷贝

2、用图来解释什么是深浅拷贝

1.无指针的浅拷贝
这里写图片描述

2.有指针的浅拷贝
这里写图片描述

3.有指针的深拷贝
 这里写图片描述

3、用代码解释深浅拷贝

1.无指针的浅拷贝

class A
{
    public:
        A(int _data):data(_data){}
        A(){}
    private:
        int data;   
};

int main()
{
    A a(5);
    A b=a;//浅拷贝 
}
     
     
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

解释:b=a;就是浅拷贝,执行完b.data=5;如果对象中没有其他资源(如:堆,文件,系统资源),深浅无差。

2.有指针的浅拷贝(导致内存泄露)

class A
{
    public:
        A(int _size):size(_size)
        {
            data=new int[size];
        }//给data分配size个内存 
        A(){}
        ~A()
        {
            delete []data;
        }//析构时释放资源 
    private:
        int *data;
        int size;   
};

int main()
{
    A a(5);
    A b=a;
}
     
     
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 这里b=a会造成未定义行为,因为类A中拷贝构造器是编译器生成的,所以b=a执行的是浅拷贝(记住:浅拷贝是对象数据之间的简单赋值)例如:b.size=a.size和b.data=a.data
  • 这里b的指针data和a的指针指向了堆上的同一块内存,a和b析构时同一块内存将会被释放两次,其结果是,有未定义的内存将会被泄露或程序奔溃!!!

3.有指针的深拷贝,(解决上面的问题)对象另开辟一块内存

class A
{
    public:
        A(int _size):size(_size)
        {
            data=new int[size];
        }//给data分配size个内存 
        A(){}
        A(const A&_A):size(_A.size)
        {
            data=new int[size];
        }//深拷贝 
        ~A()
        {
            delete []data;
        }//析构时释放资源 
    private:
        int *data;
        int size;   
};

int main()
{
    A a(5);
    A b=a;
}
     
     
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

**以上代码就没有问题了,与浅拷贝区别就是,在自己定义的拷贝函数里另开辟一块内存即深拷贝,

扫码向博主提问

浅然_

非学,无以致疑;非问,无以广识
  • 擅长领域:
  • Java
  • MySQL
    <div class="article-bar-bottom">
            <div class="article-copyright">
        版权声明:本文为博主原创文章,转载请注明出处  浅然的专栏           https://blog.csdn.net/w_linux/article/details/65450857      </div>
                    <div class="tags-box artic-tag-box">
        <span class="label">文章标签:</span>
                    <a class="tag-link" href="http://so.csdn.net/so/search/s.do?q=C++&amp;t=blog" target="_blank">C++                       </a><a class="tag-link" href="http://so.csdn.net/so/search/s.do?q=深拷贝浅拷贝&amp;t=blog" target="_blank">深拷贝浅拷贝                     </a><a class="tag-link" href="http://so.csdn.net/so/search/s.do?q=类&amp;t=blog" target="_blank">类                       </a>
    </div>
                    <div class="tags-box">
        <span class="label">个人分类:</span>
                    <a class="tag-link" href="https://blog.csdn.net/w_linux/article/category/6701432" target="_blank">【C/C++】                       </a>
    </div>
                    <div class="tags-box">
        <span class="label">所属专栏:</span>
                    <a class="tag-link" href="https://blog.csdn.net/column/details/15238.html" target="_blank">C++阅读笔记</a>

    </div>
                    <div class="tags-box hot-word">
        <span class="label">相关热词:</span>
                    <a class="tag-link" href="https://blog.csdn.net/better_xiaoxuan/article/details/52957219" target="_blank">
        c++::           </a>
                    <a class="tag-link" href="https://blog.csdn.net/k_koris/article/details/80469956" target="_blank">
        ->和c++          </a>
                    <a class="tag-link" href="https://blog.csdn.net/a7055117a/article/details/48348821" target="_blank">
        c++汉诺塔          </a>
                    <a class="tag-link" href="https://blog.csdn.net/jx232515/article/details/51547372" target="_blank">
        c++冒泡排序         </a>
                    <a class="tag-link" href="https://blog.csdn.net/qq_36221862/article/details/61413619" target="_blank">
        c++纯虚函数         </a>
                </div>
        </div>

<!-- !empty($pre_next_article[0]) -->
        <div class="related-article related-article-prev text-truncate">
    <a href="https://blog.csdn.net/w_linux/article/details/65445143">
        <span>上一篇</span>CSS三种创建和六种选择器       </a>
</div>
            <div class="related-article related-article-next text-truncate">
    <a href="https://blog.csdn.net/w_linux/article/details/65455396">
        <span>下一篇</span>C++(笔记)深浅拷贝and静态static基础练习      </a>
</div>
</div>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值