首先看一段代码:

 #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++深拷贝与浅拷贝的更多相关文章

  1. C#设计模式:原型模式(Prototype)及深拷贝、浅拷贝

    原型模式(Prototype) 定义: 原型模式:用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象.被复制的实例被称为原型,这个原型是可定制的. Prototype Pattern也是一 ...

  2. Objective-C中的深拷贝和浅拷贝

    在Objective-C中对象之间的拷贝分为浅拷贝和深拷贝.说白了,对非容器类的浅拷贝就是拷贝对象的地址,对象里面存的内容仍然是一份,没有新的内存被分配.对非容器类的深拷贝就是重写分配一块内存,然后把 ...

  3. $.extend()的深拷贝和浅拷贝详细讲解

    版权声明:作者原创,转载请注明出处! 语法:jQuery.extend( [deep ], target, object1 [, objectN ] ) 描述: 将两个或更多对象的内容合并到第一个对象 ...

  4. JavaScript中面向对象的的深拷贝和浅拷贝

    理解深拷贝和浅拷贝之前需要弄懂一些基础概念,内存中存储的变量类型分为值类型和引用类型. 1.值类型赋值的存储特点, 将变量内的数据全部拷贝一份, 存储给新的变量. 例如:var num = 123 : ...

  5. C++深拷贝与浅拷贝

    当用一个已初始化过了的自定义类类型对象去初始化另一个新构造的对象的时候,拷贝构造函数就会被自动调用.也就是说,当类的对象需要拷贝时,拷贝构造函数将会被调用.以下情况都会调用拷贝构造函数: (1)一个对 ...

  6. C++的深拷贝与浅拷贝

    对于普通类型的对象来说,它们之间的复制是很简单的,例如:int a=88;int b=a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量.下面是一个类对象拷贝的简单例子. #i ...

  7. Python赋值语句与深拷贝、浅拷贝的区别

    参考:http://stackoverflow.com/questions/17246693/what-exactly-is-the-difference-between-shallow-copy-d ...

  8. [C#进阶系列]专题一:深入解析深拷贝和浅拷贝

    一.前言 这个星期参加了一个面试,面试中问到深浅拷贝的区别,然后我就简单了讲述了它们的之间的区别,然后面试官又继续问,如何实现一个深拷贝呢?当时只回答回答了一种方式,就是使用反射,然后面试官提示还可以 ...

  9. 也来玩玩 javascript对象深拷贝,浅拷贝

    经常看到讨论c#深拷贝,浅拷贝的博客,最近js写的比较多, 所以也来玩玩js的对象拷贝. 下面是维基百科对深浅拷贝的解释: 浅拷贝 One method of copying an object is ...

  10. OC中的深拷贝与浅拷贝

    深拷贝(deep copy)与浅拷贝(shallow copy)的定义一直是有争论的. 一种理解是: 所谓的浅拷贝, 就是不完全的拷贝 NSString *s = @"123"; ...

随机推荐

  1. 安装rcssmin方法

    #安装rcssmin方法'''pip install wheelpip install rcssmin --install-option="--without-c-extensions&qu ...

  2. 1154:LETTERS

    题目链接http://bailian.openjudge.cn/practice/1154/ 总时间限制: 1000ms 内存限制: 65536kB 描述 A single-player game i ...

  3. linux软连接

    linux软连接.类似window的快捷方式可以跨磁盘块(硬连接不可以). #软硬链接 ln -sf source target ln source target #硬链接不能跨分区 #批量解压文件 ...

  4. vs2017 打开附带的localdb v13

    查看自己本机装了哪些版本的localdb 打开数据库资源管理器   添加数据库连接     选择要连接的localdb版本,这里选择的是v13版本      添加数据库   新建一个test数据库   ...

  5. xcode10 改动

    xcode10 开发环境 比  之前有了稍微的变动 1. 代码块 界面控件   图片资源等 的查看位置发生了变化 之前的开发环境  代码块  统一放在 右侧栏的下方的几个选项中 现在 统一放到了上方 ...

  6. android sdk content loader 0%不动

    Make sure that eclipse is not active. If it is active kill eclipse from the processes tab of the tas ...

  7. 【iCore1S 双核心板_ARM】例程十八:SD_IAP_FPGA实验——更新升级FPGA

    实验现象及操作说明: 1.烧写程序成功,绿色ARM·LED灯点亮,三色FPGA·LED灯循环点亮,烧写失败,如果挂载SD卡失败,红灯快闪,如果打开文件失败,蓝灯快闪,读取文件指针移动失败,白灯点亮,升 ...

  8. mac中安装lua5.1.5

    lua有一个工具lua-releng( https://github.com/openresty/openresty-devel-utils/blob/master/lua-releng) 用来检测代 ...

  9. SparkStreaming:关于checkpoint的弊端

    当使用sparkstreaming处理流式数据的时候,它的数据源搭档大部分都是Kafka,尤其是在互联网公司颇为常见. 当他们集成的时候我们需要重点考虑就是如果程序发生故障,或者升级重启,或者集群宕机 ...

  10. Zookeeper客户端介绍

    客户端是开发人员使用Zookeeper的主要的途径,以下内容将对Zookeeper的内部原理进行详细的学习和讲解.ZooKeeper的客户端主要有一下几个核心组件组成: Zookeeper:提供客户端 ...