目录
一.什么是浅拷贝,什么是深拷贝
浅拷贝:位拷贝,拷贝构造函数,赋值重载
多个对象共用同一块资源,同一块资源释放多次,崩溃或者内存泄漏
深拷贝:每个对象共同拥有自己的资源,必须显式提供拷贝构造函数和赋值运算符
二.浅拷贝发生错误过程
在程序运行过程中,如果一个对象的变量B动态开辟了一个内存空间,在进行位拷贝的时候,就把B的值完全赋给A。在赋值过程中,就是A中变量与B中变量指向同一内存空间。但是如果B将内存释放,
A中的指针就没有了指向,也就是野指针,这样就会发生运行错误 。
三.关于浅拷贝的详细讨论
1.默认构造函数可以完成对象的数据成员简单的复制
2.对象的数据资源是由指针指向的堆时,默认的拷贝构造函数只是将指针复制3.有指针,有默认的拷贝构造函数才会发生浅拷贝
#include <iostream>
using namespace std;
class Line{
public:
int getLength( void );
Line( int len );
~Line();
void set(int m)
{
*ptr=m;
}
private:
int *ptr;
};
Line::Line(int len)
{
cout << "调用构造函数" << endl;
ptr = new int;//在堆上开辟一个空间,指针ptr指向堆上新分配的内存空间
*ptr = len;//把传递进来的参数放在ptr指向的内存空间中
}
Line::~Line()
{
cout << "开始释放内存" << endl;
delete ptr;
cout << "释放内存完毕" << endl;
}
int Line::getLength( )
{
return *ptr;//返回ptr所指向空间里面的值
}
int main( )
{
Line line0(10); //创建line0这个对象,并且调用构造函数
cout << "line0 大小 : " << line0.getLength() <<endl;
Line line1=line0;//用line0初始化line1,一定会调用拷贝构造函数,但是没有自定义的拷贝构造函数,
//所以一定会调用默认的拷贝构造函数,而前面提到默认的拷贝构造函数只是将指针复制,
//所以line0和line1的指针指向同一个内存空间 ,该内存空间存放的是10
cout << "line1 大小 : " << line1.getLength() <<endl;
line1.set(100);//line1通过set()函数去修改它的指针所指向空间里面的值,即将10改为100
cout << "line0 大小 : " << line0.getLength() <<endl;//输出100
cout << "line1 大小 : " << line1.getLength() <<endl;//输出100
return 0;//程序结束后先析构了line1,等到析构line0的时候,指针已经悬空了没有可以析构的
}
四.深拷贝
#include <iostream>
using namespace std;
class Line{
public:
int getLength( void );
Line( int len );
Line( const Line &obj); //自定义了一个拷贝构造函数,类内声明
~Line();
void set(int m)
{
*ptr=m;
}
private:
int *ptr;
};
Line::Line(int len)
{
cout << "调用构造函数" << endl;
ptr = new int;//在堆上申请一个空间,指针ptr指向堆上新分配的内存空间
*ptr = len;
}
Line::Line(const Line &obj)//拷贝构造函数在类外定义
{
cout << "调用拷贝构造函数并为指针 ptr 分配内存" << endl;
ptr = new int;//在堆上申请一个空间,指针ptr指向堆上新分配的内存空间,此时的ptr是当前对象line1的ptr
*ptr = *obj.ptr;//将obj就是line0,*obj.ptr是将line0指向的内存空间里面的10取出来,
//放进当前line1的ptr指向的内存空间
}
Line::~Line(){
cout << "开始释放内存" << endl;
delete ptr;
cout << "释放内存完毕" << endl;
}
int Line::getLength( )
{
return *ptr;
}
void display(Line obj){
cout << "line 大小 : " << obj.getLength() <<endl;
}
int main( )
{
Line line0(10); //创建line0这个对象,并且调用构造函数,将10传参给len
cout << "line0 大小 : " << line0.getLength() <<endl;
Line line1=line0;//用line0初始化line1,一定会调用拷贝构造函数,
//所以一定会调用自定义的拷贝构造函数,
cout << "line1 大小 : " << line1.getLength() <<endl;
line1.set(100);//line1通过set()函数去修改它的指针所指向空间里面的值,即将10改为100
cout << "line0 大小 : " << line0.getLength() <<endl;//输出10
cout << "line1 大小 : " << line1.getLength() <<endl;//输出100
return 0;//程序结束后先析构了line1,然后析构line0
}