1. 浅拷贝以及内存泄漏的背景

先考虑一种情况,对一个已知对象进行拷贝,编译系统会自动调用一种构造函数——拷贝构造函数,如果用户未定义拷贝构造函数,则会调用默认拷贝构造函数

#include <iostream>
#include "student.h"
int main()
{Student s1;Student s2(s1);//Student s2 = s1;//复制对象return 0;
}
//仔细看,对象中存在一个指针成员,这个是我们研究的核心#ifndef STUDENT_H
#define STUDENT_H
class Student
{private:int num;char *name;public:Student();~Student();
};#endif
// 注意看析构函数,我们对对象的指针成员进行内存的释放
#include "student.h"
#include <iostream>
using namespace std;Student::Student()
{name = new char(20);cout << "Student" << endl;}
Student::~Student()
{cout << "~Student " << (int)name << endl;delete name;name = NULL;
}

执行结果:调用一次构造函数,调用两次析构函数,两个对象的指针成员所指内存相同,这会导致什么问题呢?

name指针被分配一次内存,但是程序结束时该内存却被释放了两次,会造成内存泄漏问题!

这是由于编译系统在我们没有自己定义拷贝构造函数时,会在拷贝对象时调用默认拷贝构造函数,进行的是浅拷贝!即对指针name拷贝后会出现两个指针指向同一个内存空间。

所以,在对含有指针成员的对象进行拷贝时,必须要自己定义拷贝构造函数,使拷贝后的对象指针成员有自己的内存空间,即进行深拷贝,这样就避免了内存泄漏发生。

2. 深拷贝进行内存泄漏进行拯救

//student.h#ifndef STUDENT_H
#define STUDENT_H
class Student
{private:int num;char *name;public:Student();//构造函数~Student();//析构函数Student(const Student &s); //重要:拷贝构造函数,const防止对象被改变
};#endif
//student.cpp#include "student.h"
#include <iostream>
#include <string.h>
using namespace std;Student::Student()
{name = new char(20);cout << "Student " << endl;
}Student::~Student()
{cout << "~Student " << (int)name << endl;delete name;name = NULL;
}Student::Student(const Student &s)
{name = new char(20);  // 对于每一次对象的引用,我们都重新开辟内存空间memcpy(name, s.name, strlen(s.name));cout << "copy Student " << endl;
}

执行结果:调用一次构造函数,一次自定义拷贝构造函数,两次析构函数。两个对象的指针成员所指内存不同。

总结:浅拷贝只是对指针的拷贝,拷贝后两个指针指向同一个内存空间,深拷贝不但对指针进行拷贝,而且对指针指向的内容进行拷贝,经深拷贝后的指针是指向两个不同地址的指针。

再说几句:

当对象中存在指针成员时,除了在复制对象时需要考虑自定义拷贝构造函数,还应该考虑以下两种情形:

1.当函数的参数为对象时,实参传递给形参的实际上是实参的一个拷贝对象,系统自动通过拷贝构造函数实现;

2.当函数的返回值为一个对象时,该对象实际上是函数内对象的一个拷贝,用于返回函数调用处。

3. 参考文献

《C++ primer》

深拷贝拯救指针重复释放(浅拷贝)造成的内存泄漏相关推荐

  1. 假笨说-谨防JDK8重复类定义造成的内存泄漏

    概述 如今JDK8成了主流,大家都紧锣密鼓地进行着升级,享受着JDK8带来的各种便利,然而有时候升级并没有那么顺利?比如说今天要说的这个问题.我们都知道JDK8在内存模型上最大的改变是,放弃了Perm ...

  2. 虚析构函数? vptr? 指针偏移?多态数组? delete 基类指针 内存泄漏?崩溃?...

    五条基本规则: 1.如果基类已经插入了vptr, 则派生类将继承和重用该vptr.vptr(一般在对象内存模型的顶部)必须随着对象类型的变化而不断地改变它的指向,以保证其值和当前对象的实际类型是一致的 ...

  3. 智能指针的释放_堆栈里的悄悄话——智能指针

    来自公众号:编程技术宇宙 1 栈里的对象 "构造完毕,请睁开眼吧!",迷迷糊糊中,听着这个声音,我睁开了眼睛,一位小哥映入眼帘."你是谁?我是谁?这又是什么地方?&quo ...

  4. c/c++教程 - 2.4.2.5 深拷贝和浅拷贝,堆区内存重复释放

    目录 4.2.5 深拷贝与浅拷贝(非常重要,视频P110) 相关教程 4.2.5 深拷贝与浅拷贝(非常重要,视频P110) 深浅拷贝是面试的经典问题. 浅拷贝:简单的赋值拷贝操作. 深拷贝:在堆区重新 ...

  5. 智能指针的释放_手把手教你实现智能指针

    一. 为什么使用智能指针 C++的内存管理是让很多人头疼的事,因为C++语言中没有垃圾回收机制,当我们通过new语句动态申请堆空间时,用完这个堆空间时就得用delete语句释放申请的堆空间,不然就会导 ...

  6. 智能指针的释放_看完这篇,别再说不会智能指针了

    C++智能指针 一.智能指针的作用 上一篇介绍了内存池的原理和实现,详情请见内存池设计与实现: 内存池可以帮助我们有效的对内存进行管理,智能指针可以很方便的管理指针,避免出现内存泄漏: 智能指针的作用 ...

  7. qt 如何 指针 自动 释放内存_要是面试官再问你智能指针的问题,就拿这篇文章“盘他”!!!...

    前一段时间,有不少朋友问我关于智能指针的问题,并且反映经常会在面试中被面试官问到,所以今天小豆君就来讲讲我对智能指针的理解,希望能对大家有所帮助 既然讲智能指针,我们就先来看看它为什么会出现. 1 传 ...

  8. c语言 结构体指针 free 释放内存

    1.结构体定义如下 struct node {int footpath_id;double deltaz;char* address;char* clue_sa; }; struct dict {st ...

  9. 释放参数BSTR使用误区以及隐藏的内存破坏和内存泄漏

    PS:明天上午,非常郁闷,有很多简单基础的问题搞得我有些迷茫,哎,代码几天不写就忘.目前又不当COO,还是得用心记代码哦! BSTR应用误区以及隐藏的内存损坏和内存泄漏 作者:magictong 简介 ...

最新文章

  1. 原来deepin部署环境还是那么简单(只不过要用root权限)
  2. 额,你在main.xml中加了一个id以后,要右键点save,才会将这个id加入到R中,否则是没有的。。。R里的东西是程序自动生成的~~~...
  3. dataframe中将一列数据切分成多列
  4. LeetCode 1091. 二进制矩阵中的最短路径(BFS)
  5. 【WS-Federation】到底有多少公司在用WS-Federation
  6. ssh服务及安全配置
  7. 如何做出酷炫且实用的可视化大屏?Excel和PPT该淘汰了
  8. vulhub靶场sql注入漏洞复现
  9. 身份证OCR识别SDK
  10. linux锐捷认证成功无法上网,如何修复win7系统锐捷认证成功但是却无法上网的操作教程...
  11. 这次要讲不清前后端分离,我都怎么地!
  12. 做word计算机海报图片,怎么用word制作海报 海报制作方法
  13. html制作好看的五子棋(源码)
  14. java 百度ocr识别身份证,营业执照流程
  15. 基于SpringBoot实现邮箱找回密码
  16. 耳机四根线的图解_耳机线材编法汇总
  17. 迅速提高代码编写速度的训练方法
  18. iPhone/iPad/iTouch配置Bash/C/C++/OC/Java/Theos/MySQL/Python开发环境! 让我告诉你iOS的魅力~
  19. 应用案例 | 2007 款奥迪 A4 车发动机故障灯异常点亮-
  20. python开源oa系统_「开源」目前见过的最好的开源OA产品

热门文章

  1. iOS Assigning to 'idXXXDelegate' from incompatible type 'BViewController *__strong'
  2. KBMMW 4.6 正式版发布
  3. poj 1981(单位圆覆盖点)
  4. 费马素性测试和米勒—拉宾素性测试
  5. JSP简单练习-使用JDOM创建xml文件
  6. Java杂记之JVM内存模型
  7. 今天仔细学习了html加载执行的顺序
  8. dell raid配置
  9. js的时间函数实现一个电子表
  10. win32应用程序创建流程