深拷贝与浅拷贝
来源:互联网 发布:金域名苑 编辑:程序博客网 时间:2024/06/05 05:45
默认情况下,c++编译器至少为我们写的类增加3个函数
1.默认构造函数(无参,函数体为空)
2.默认析构函数(无参,函数体为空)
3.默认拷贝构造函数,对类中非静态成员属性简单值拷贝
如果用户定义拷贝构造函数,c++不会再提供任何默认构造函数
如果用户定义了普通构造(非拷贝)函数,则c++编译器不在为我们提供默认的无参构造函数,但是会提供默认拷贝构造;
在同类中的两个对象之间可以赋值,这样使得两个对象的值相同,但是这两个对象仍然是两个不同的对象;
下面来个示例代码说明类中的浅拷贝问题:
#include<stdlib.h>#include <string>#include <iostream>using namespace std;class People{public: People(string name,int age):m_Pname(name),m_age(age){cout<<"构造函数执行"<<endl;} People(){} void display() { cout<<"m_Pname = "<<m_Pname<<endl; cout<<"m_age = "<<m_age<<endl; } ~People(){cout<<"析构函数执行"<<endl;}private: string m_Pname; int m_age;};void myFunc(){ People p1("lixiaogang",23); People p2 = p1; /* People p2 = p1;该语句会发生一个拷贝构造函数调用; 注意:People p2 = p1;不同于:People p1("lixiaogang",23);People p2;p2 = p1;这里发生的操作是“赋值操作”,即直接将对象p1的值赋值给p2对象 */ p1.display(); puts("----------------"); p2.display();}int main(){ myFunc(); system("pause"); return 0;}
代码执行后结果为:
构造函数执行m_Pname = lixiaogangm_age = 23-----------------m_Pname = lixiaogangm_age = 23析构函数执行析构函数执行
这里的拷贝构造函数执行后没有任何的bug
出现,现在我们把m_Pname
改为一个指向char 型的指针: char *pName
之后,再来调试,代码如下:
#include<stdlib.h>#include <string.h>#include <iostream>using namespace std;class People{public: People(const char *name,int age) { cout<<"构造函数执行"<<endl; int len = strlen(name); this->m_Pname = new char[ len + 1]; strcpy(this->m_Pname,name); this->m_age = age; } People(){} void display() { cout<<"m_Pname = "<<m_Pname<<endl; cout<<"m_age = "<<m_age<<endl; } ~People() { cout<<"析构函数执行"<<endl; if (this->m_Pname != NULL ) { delete[] m_Pname; } }private: char *m_Pname; int m_age;};void myFunc(){ People p1("lixiaogang",23); People p2 = p1; p1.display(); puts("----------------"); p2.display();}int main(){ myFunc(); system("pause"); return 0;}
再来运行该代码,便会出现bug
,程序直接死掉;如图:
分析原因在于程序中m_Pname指针在堆区中申请了一段内存空间,执行People p2 = p1语句时,把p1所指向的内存地址也给了p2一份,于是p2、p1都指向了同一个空间中,默认拷贝构造函数执行完成后,不会又问题,问题出现的是在析构函数阶段,从上面的代码段中可以看到“析构函数”被执行了两次,即就是p2,p1分别执行了一次析构;因此析构函数执行的时候,同一段内存空间被释放了两次,所以出现了错误(一个内存被释放之后, 该指针就不再执行这段内存空间了,如果此时再来对这个内存空间进行析构操作,这是属于非法的操作); 原理图如下:
解决方案是“自己重新定义一个拷贝构造函数,为新的对象p2
分配一个新的内存空间,这样两个对象所指向的内存空间不是同一块地址,因此执行析构函数的时候也就不会bug
了。
代码如下:
#include<stdlib.h>#include <string.h>#include <iostream>using namespace std;class People{public: People(const char *name,int age) { cout<<"构造函数执行"<<endl; int len = strlen(name); this->m_Pname = new char[ len + 1]; strcpy(this->m_Pname,name); this->m_age = age; } People(){} /**** 拷贝构造函数 ****/ People(const People &p) { this->m_Pname = new char[strlen(p.m_Pname)+1]; strcpy(this->m_Pname,p.m_Pname); this->m_age = p.m_age; } void display() { cout<<"m_Pname = "<<m_Pname<<endl; cout<<"m_age = "<<m_age<<endl; } ~People() { cout<<"析构函数执行"<<endl; if (this->m_Pname != NULL ) { delete[] m_Pname; } }private: char *m_Pname; int m_age;};void myFunc(){ People p1("lixiaogang",23); People p2 = p1; p1.display(); puts("----------------"); p2.display();}int main(){ myFunc(); system("pause"); return 0;}
再次来运行程序,则完美运行,不会出现bug
;其原理图如下:
结论:当类中有成员变量是指针时候,需要我们去为其分配内存空间,因此一旦类中有成员变量是指针的时候,往往需要我们自己提供几个函数,分别是拷贝构造函数、析构函数、构造函数、赋值函数。
- 深拷贝与浅拷贝
- 深拷贝与浅拷贝
- 深拷贝与浅拷贝
- “浅拷贝”与“深拷贝”
- 深拷贝与浅拷贝
- 深拷贝与浅拷贝
- 深拷贝与浅拷贝
- 浅拷贝与深拷贝
- 深拷贝与浅拷贝
- 深拷贝与浅拷贝
- “浅拷贝”与“深拷贝”
- 深拷贝与浅拷贝
- 浅拷贝与深拷贝
- 深拷贝与浅拷贝
- 浅拷贝与深拷贝
- 深拷贝与浅拷贝
- 深拷贝与浅拷贝
- 深拷贝与浅拷贝
- 3. Python开发--基本数据类型操作方法
- Android App 启动页(Splash)黑/白闪屏现象
- 动态链接原理分析
- HDU 1754I Hate It(线段树)
- 课堂笔记_ B样条曲线和NUBRS
- 深拷贝与浅拷贝
- 奇异值分解(SVD) --- 线性变换几何意义
- java入门(数组)
- java接口
- 欢迎使用CSDN-markdown编辑器
- Python变量命名用法(一般变量、常量、私有变量、内置变量)
- 四种会话跟踪技术
- TensorFlowOnSpark安装教程
- selenium和Firefox版本不兼容