Cpp下的深拷贝与浅拷贝探究
下面,通过代码来说说C++中的深浅拷贝
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Name
{
public:
Name(const char*myp){
m_len = strlen(myp);
mp = (char*)malloc(m_len + );
strcpy(mp, myp);
}
~Name(){
if (mp != NULL)
{
free(mp);
mp = NULL;
m_len = ;
}
}
private:
char *mp;
int m_len;
}; void playmain(){
Name obj1("abcdef");
Name obj2 = obj1; // 执行默认拷贝构造函数
}
int main()
{
playmain();
cout <<"hello world"<<endl;
system("pause");
return ;
}
我们通过断点,一步一步地调试程序:

继续往下走:

继续往下走:

由于我们并没有重写自己的拷贝构造函数,因此执行的是默认的拷贝构造函数。当Name obj2=obj1执行完毕后,也就是函数playmain()执行完毕了,开始调用对象的析构函数:

首先析构的是obj2,当其析构完毕后,程序返回:

我们接着往下走:

继续F11往下走,我们会发现程序崩溃了:

下面,我们来分析一下,为什么程序会崩溃在这里?原因很简单,因为我们重写自己的拷贝构造函数,而使用了默认的拷贝构造函数,也就是C++编译器为我们进行了一次浅拷贝。那么何为浅拷贝呢?下面来看张图:

也就是说,当我们第一次析构对象obj2的时候,已经将内存空间0x1111释放了,而obj1和obj2都指向了同一块内存空间,当obj1执行析构函数的时候,它所指向的内存空间已经被释放,再次进程释放,肯定程序会崩溃。到此 ,我们清楚知道,导致程序崩溃的原因是C++编译器仅仅执行了浅拷贝,而浅拷贝的根源在于我们没有重写自己的拷贝构造函数,所以解决办法,当然是重写自己的拷贝构造函数,从而实现深拷贝-------将对象完完全全的赋值一份(包括指针指向的内存空间也复制一份)

再次执行程序,不会出现崩溃现象。上述对应的内存四区模型如下:

同理,如下代码中也会出现程序崩溃,也需要我们显式重载"="运算符

没有重载=运算符内存四区模型如下:
初始条件:

执行等号操作后:

解决方案:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std; class Name
{
public:
Name(const char *myp)
{
m_len = strlen(myp);
m_p =(char *) malloc(m_len + );
strcpy(m_p, myp);
} //解决方案: 手工的编写拷贝构造函数 使用深copy
Name(const Name& obj1)
{
m_len = obj1.m_len;
m_p = (char *)malloc(m_len + );
strcpy(m_p, obj1.m_p);
}
//obj3 = obj1; // C++编译器提供的 等号操作 也属 浅拷贝
//obj3.operator=(obj1)
Name& operator=(Name &obj1) // 重载等号运算符
{
//先释放旧的内存
if (this->m_p != NULL)
{
delete[] m_p;
m_len = ;
}
//2 根据obj1分配内存大小
this->m_len = obj1.m_len;
this->m_p = new char [m_len+]; //把obj1赋值
strcpy(m_p, obj1.m_p);
return *this;
}
~Name()
{
if (m_p != NULL)
{
free(m_p);
m_p = NULL;
m_len = ;
}
}
protected:
private:
char *m_p ;
int m_len;
}; //对象析构的时候 出现coredump
void objplaymain()
{
Name obj1("abcdefg");
Name obj2 = obj1; //C++编译器提供的 默认的copy构造函数 浅拷贝
Name obj3("obj3"); obj3 = obj1; // C++编译器提供的 等号操作 也属 浅拷贝
//obj3.operator=(obj1)
//operato=(Name &obj1)
obj1 = obj2 = obj3;
//obj2.operator=(obj3);
//obj1 = void;
} void main()
{
objplaymain();
cout<<"hello..."<<endl;
system("pause");
return ;
}
Cpp下的深拷贝与浅拷贝探究的更多相关文章
- Python中list的复制及深拷贝与浅拷贝探究
在Python中,经常要对一个list进行复制.对于复制,自然的就有深拷贝与浅拷贝问题.深拷贝与浅拷贝的区别在于,当从原本的list复制出新的list之后,修改其中的任意一个是否会对另一个造成影响,即 ...
- .net平台下深拷贝和浅拷贝
在.net类库中,对象克隆广泛存在于各种类型的实现中,凡是实现了ICloneable接口的类型都具备克隆其对象实例的能力.所以本文讲述的深拷贝和浅拷贝也是在实现ICloneable接口的基础上进行的. ...
- 探究JS中对象的深拷贝和浅拷贝
深拷贝和浅拷贝的区别 在讲深拷贝和浅拷贝的区别之前,回想一下我们平时拷贝一个对象时是怎么操作的?是不是像这样? var testObj1 = {a: 1, b:2}, testObj2=testObj ...
- 浅谈.net平台下深拷贝和浅拷贝
在.net类库中,对象克隆广泛存在于各种类型的实现中,凡是实现了ICloneable接口的类型都具备克隆其对象实例的能力.所以本文讲述的深拷贝和浅拷贝也是在实现ICloneable接口的基础上进行的 ...
- C++之拷贝构造函数、深拷贝、浅拷贝
C++ Code 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849 ...
- Objective-C中的深拷贝和浅拷贝
在Objective-C中对象之间的拷贝分为浅拷贝和深拷贝.说白了,对非容器类的浅拷贝就是拷贝对象的地址,对象里面存的内容仍然是一份,没有新的内存被分配.对非容器类的深拷贝就是重写分配一块内存,然后把 ...
- $.extend()的深拷贝和浅拷贝详细讲解
版权声明:作者原创,转载请注明出处! 语法:jQuery.extend( [deep ], target, object1 [, objectN ] ) 描述: 将两个或更多对象的内容合并到第一个对象 ...
- C++的深拷贝与浅拷贝
对于普通类型的对象来说,它们之间的复制是很简单的,例如:int a=88;int b=a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量.下面是一个类对象拷贝的简单例子. #i ...
- [C#进阶系列]专题一:深入解析深拷贝和浅拷贝
一.前言 这个星期参加了一个面试,面试中问到深浅拷贝的区别,然后我就简单了讲述了它们的之间的区别,然后面试官又继续问,如何实现一个深拷贝呢?当时只回答回答了一种方式,就是使用反射,然后面试官提示还可以 ...
随机推荐
- Linux下如何强制中断一个程序的执行?
CTRL + C 中断 CTRL + Z 暂时放到后台 CTRL + D 保存退出
- Python学习笔记(九)返回函数
摘抄:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014318352367 ...
- 超越icon font
很久以前,我们如何使用图标? 1.切图 2.拼合(Sprites) 原始社会啊! 后来CSSGagagrunt-css-sprite 字体图标 相见不曾相识 Emoji绘文字 iconfont.cn直 ...
- Javascript判断Chrome浏览器
今天分享一下如何通过Javascript来判断Chrome浏览器,这里是通过userAgent判断的,检测一下userAgent返回的字符串里面是否包含“Chrome”, 具体怎么检测是通过index ...
- 应用于网站导航中的 12 个 jQuery 插件
当考虑到网页设计时,导航被认为是使网页以用户友好方式展现的一个重要部分.在现代的交互网站中,导航起着至关重要的作用,如果没有正确地处理会影响你网站的访问.适当的导航工具能够帮助用户在网站的不同页面内容 ...
- HDU 2044 Coins
有一只经过训练的蜜蜂只能爬向右侧相邻的蜂房,不能反向爬行.请编程计算蜜蜂从蜂房a爬到蜂房b的可能路线数. 其中,蜂房的结构如下所示. Input输入数据的第一行是一个整数N,表示测试实例的个数,然 ...
- 2017ACM暑期多校联合训练 - Team 6 1003 HDU 6098 Inversion (模拟)
题目链接 Problem Description Give an array A, the index starts from 1. Now we want to know Bi=maxi∤jAj , ...
- HDU 3790 最短生成树 (最短路)
题目链接 Problem Description 给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的. ...
- JS设计模式——2.初识接口
什么是接口 接口提供了一种用以说明一个对象应该具有哪些方法的手段. 接口之利 1.接口具有自我描述性从而促进代码的重用 2.接口有助于稳定不同中的类之间的通信方式 3.测试和调试也变得更轻松 接口之弊 ...
- ecshop代码修改后提交,无法立即生效
今天帮一朋友部署一网站.成品的ecshop模版站.在搭建好xammp集成环境,导入数据库,修改配置文件后,报了一大堆错. 其中第一个是关于废弃preg_replace中/e这种用法的,因为存在漏洞,一 ...