关于c++深拷贝与浅拷贝
首先看一段代码:
#include<iostream>
#include<cstring>
#include<malloc.h>
using namespace std; class Teacher{
public:
Teacher(int id,char *name){
m_id=id; m_name=(char*)malloc(strlen(name)+);//由于显示析构函数中free内存空间,因而必须malloc
strcpy(m_name,name);
} void Print(){
cout<<"id="<<m_id<<" name="<<m_name<<endl;
} ~Teacher(){/*显示析构函数*/
cout<<"Teacher()..."<<endl;
if(m_name!=NULL){
free(m_name);
m_name=NULL;
}
}
private:
int m_id;
char *m_name;
}; int main(){
Teacher t1(,"zhangsan");
t1.Print(); return ;
}
浅谈析构函数特点:
1.函数名是在类名前加上~,无参数且无返回值。
2.一个类只能有且有一个析构函数,如果没有显式的定义,系统会生成一个缺省的析构函数(合成析构函数)。
3.析构函数不能重载。每有一次构造函数的调用就会有一次析构函数的调用。
#include<iostream>
#include<cstring>
#include<malloc.h>
using namespace std; class Teacher{
public:
Teacher(int id,char *name){
cout<<"Teacher(int,char*)..."<<endl;
m_id=id; int len=strlen(name);
m_name=(char*)malloc(len+);//由于显示析构函数中free内存空间,因而必须malloc
strcpy(m_name,name);
}
/*默认拷贝构造函数,浅拷贝!!!*/
Teacher(const Teacher& another){
m_id=another.m_id;
m_name=another.m_name;
}
void Print(){
cout<<"id="<<m_id<<" name="<<m_name<<endl;
} ~Teacher(){/*显示析构函数*/
cout<<"Teacher()..."<<endl;
if(m_name!=NULL){
free(m_name);
m_name=NULL;
}
}
private:
int m_id;
char *m_name;
}; void test(){
Teacher t1(,"xiaoming");
t1.Print(); Teacher t2(t1);//t2的默认拷贝构造
t2.Print();
} int main(){
test(); return ;
}
【浅拷贝】是增加了一个指针,指向原来已经存在的内存。
而【深拷贝】是增加了一个指针,并新开辟了一块空间,让指针指向这块新开辟的空间

在test函数结束时,t1和t2都会走一遍析构函数,释放内存空间,t2后执行,因而先走析构函数,将name的内存空间释放掉,当t1走析构函数时,会再次进行m_name的内存空间释放,但由于这块内存空间在t2走析构函数时已经被释放掉了,所以在这里会引发段错误!!!,这也就是浅拷贝的危害。。。
为了避免浅拷贝引发的段错误,因而我们需要进行深拷贝,重写拷贝构造函数
#include<iostream>
#include<cstring>
#include<malloc.h>
using namespace std; class Teacher{
public:
Teacher(int id,char *name){
cout<<"Teacher(int,char*)..."<<endl;
m_id=id; int len=strlen(name);
m_name=(char*)malloc(len+);//由于显示析构函数中free内存空间,因而必须malloc
strcpy(m_name,name);
}
/*重写拷贝构造函数,深拷贝*/
Teacher(const Teacher& another){
m_id=another.m_id;
//深拷贝//
int len=strlen(another.m_name);
m_name=(char*)malloc(len+);
strcpy(m_name,another.m_name);
}
void Print(){
cout<<"id="<<m_id<<" name="<<m_name<<endl;
} ~Teacher(){/*显示析构函数*/
cout<<"Teacher()..."<<endl;
if(m_name!=NULL){
free(m_name);
m_name=NULL;
}
}
private:
int m_id;
char *m_name;
}; void test(){
Teacher t1(,"xiaoming");
t1.Print(); Teacher t2(t1);//t2的默认拷贝构造
t2.Print();
} int main(){
test(); return ;
}
关于c++深拷贝与浅拷贝的更多相关文章
- C#设计模式:原型模式(Prototype)及深拷贝、浅拷贝
原型模式(Prototype) 定义: 原型模式:用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象.被复制的实例被称为原型,这个原型是可定制的. Prototype Pattern也是一 ...
- Objective-C中的深拷贝和浅拷贝
在Objective-C中对象之间的拷贝分为浅拷贝和深拷贝.说白了,对非容器类的浅拷贝就是拷贝对象的地址,对象里面存的内容仍然是一份,没有新的内存被分配.对非容器类的深拷贝就是重写分配一块内存,然后把 ...
- $.extend()的深拷贝和浅拷贝详细讲解
版权声明:作者原创,转载请注明出处! 语法:jQuery.extend( [deep ], target, object1 [, objectN ] ) 描述: 将两个或更多对象的内容合并到第一个对象 ...
- JavaScript中面向对象的的深拷贝和浅拷贝
理解深拷贝和浅拷贝之前需要弄懂一些基础概念,内存中存储的变量类型分为值类型和引用类型. 1.值类型赋值的存储特点, 将变量内的数据全部拷贝一份, 存储给新的变量. 例如:var num = 123 : ...
- C++深拷贝与浅拷贝
当用一个已初始化过了的自定义类类型对象去初始化另一个新构造的对象的时候,拷贝构造函数就会被自动调用.也就是说,当类的对象需要拷贝时,拷贝构造函数将会被调用.以下情况都会调用拷贝构造函数: (1)一个对 ...
- C++的深拷贝与浅拷贝
对于普通类型的对象来说,它们之间的复制是很简单的,例如:int a=88;int b=a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量.下面是一个类对象拷贝的简单例子. #i ...
- Python赋值语句与深拷贝、浅拷贝的区别
参考:http://stackoverflow.com/questions/17246693/what-exactly-is-the-difference-between-shallow-copy-d ...
- [C#进阶系列]专题一:深入解析深拷贝和浅拷贝
一.前言 这个星期参加了一个面试,面试中问到深浅拷贝的区别,然后我就简单了讲述了它们的之间的区别,然后面试官又继续问,如何实现一个深拷贝呢?当时只回答回答了一种方式,就是使用反射,然后面试官提示还可以 ...
- 也来玩玩 javascript对象深拷贝,浅拷贝
经常看到讨论c#深拷贝,浅拷贝的博客,最近js写的比较多, 所以也来玩玩js的对象拷贝. 下面是维基百科对深浅拷贝的解释: 浅拷贝 One method of copying an object is ...
- OC中的深拷贝与浅拷贝
深拷贝(deep copy)与浅拷贝(shallow copy)的定义一直是有争论的. 一种理解是: 所谓的浅拷贝, 就是不完全的拷贝 NSString *s = @"123"; ...
随机推荐
- centos7上 docket无权限的问题
2.4 centos7上 docket无权限的问题,解决方案: https://stackoverflow.com/questions/24288616/permission-denied-on-ac ...
- typescript 与 js 开发 react 的区别
一.从定义文件格式方面说1.传统的开发模式可以定义js文件或者jsx文件2.利用ts开发定义的文件格式tsx二.定义state的状态来说1.传统的方式直接在构造函数中使用 constructor(){ ...
- PL/SQL学习笔记之日期时间
一:PL/SQL时间相关类型 PL/SQL提供两个和日期时间相关的数据类型: 日期时间(Datetime)数据类型 时间间隔类型 二:日期时间类型 datetime数据类型有: DATE TIMEST ...
- Redis 为什么使用单进程单线程方式也这么快(转载)
Redis 采用的是基于内存的采用的是单进程单线程模型的 KV 数据库,由 C 语言编写.官方提供的数据是可以达到100000+的 qps.这个数据不比采用单进程多线程的同样基于内存的 KV 数据库 ...
- 摘:PC客户端 XP兼容性调查
现象1:XP SP2下,客户端安装失败(或者启动失败) 解决方案:需要安装以下3个补丁(已经集成到安装包中) ==系统Hotfix(仅仅XP SP2需要安装): http://support.micr ...
- hive SQL 静态分区和 动态分区
Hive 分区介绍: hive中简单介绍分区表(partition table),含动态分区(dynamic partition)与静态分区(static partition) hive中创建分区表没 ...
- npm WARN React-native@0.35.0 requires a peer of react@~15.3.1 but none was installed.
解决方案: 方法一: npm install -save react@~15.3.1 方法二:在package.json中可以添加依赖 "dependencies": { &quo ...
- 10款基于jquery的web前端动画特效
1.jQuery横向手风琴图片切换动画 之前我们为大家分享过很多款基于jQuery和CSS3的手风琴菜单和手风琴焦点图插件,比如CSS3响应式垂直手风琴菜单和jQuery横向手风琴图片展示插件.今天要 ...
- VM虚拟机下安装CentOS_6.5_x64
在开始Linux的学习之前,我们必须要有一个实验环境.这里我选择了安装CentOS-6.5-x86_64的Minimal版本,大家也可以选择安装其他的Linux发行版.选择CentOS主要还是因为它比 ...
- count(*)、count(1)和count(列名)的区别
count(*).count(1)和count(列名)的区别 1.执行效果上: l count(*)包括了所有的列,相当于行数,在统计结果的时候,不会忽略列值为NULL l count(1)包 ...