C++ 深拷贝和浅拷贝

拷贝的两种方式:浅拷贝、深拷贝

浅拷贝就是对象的数据成员之间的简单赋值,如果设计了类而没有提供拷贝构造函数,当用该类的一个对象去给另一个对象赋值是所执行的过程就是浅拷贝。

如:

class A

{

public:

A(int _data) :data(_data){}

A(){}

private:

int data;

};

int main

{

A a(5), b = a;

}

---------------------------------------------------------------

b   = a;----就是浅拷贝,执行后b.data = 5;

当数据成员中没有指针时,浅拷贝是可行的,但当数据成员中有指针时,如果采用简单的浅拷贝,则两类中的两个指针将指向同一个地址,当对象结束时,会调用两次析构函数,而导致指针悬挂现象(如果一个地方指针既不为空,也没有设置为指向一个已知的对象,这样的指针称为悬挂指针)

 深拷贝和浅拷贝的区别就在于深拷贝会在堆内存中另外申请空间来存储数据,从而也就解决了指针悬挂。
如:
class A
{
public:
	A (int _size):size(_size)
	{
		data = new int[size];	
	}
	A(){};
	A(const A&  _A):size(_A.size)
	{
		data = new int [size];
	}
	~A()
	{
		delete[] data;
	}
private:
	int *data;
	int  size;
};

int main()

{

A a(5), b = a;

}


例程(浅拷贝):--转载

class Cperson

{

public:

Cperson(int age);

void Print(void);

private:

int m_age;

};

Cperson::Cperson(int age):m_age(age)

{

}

void Cperson::Print(void)

{

cout << "My age is " << m_age << endl;

}

void main(void)

{

Cperson Tom(10);

Tom.Print();


Cperson Jim(Tom);

Jim.Print();

}

运行结果:

My age is 10

My age is 10


结果分析:

对应语句Cperson Jim(Tom) 编译器将自动生成一个默认的拷贝构造函数。


错误的浅拷贝:


class Cperson
{

public:
Cperson(int age,char *name);

~Cperson();

void Print(void);

private:

int m_age;

char *m_name;

};

Cperson::Cperson(int age, char *name)

{

m_name = new char[strlen(name)  + 1 ];

if(m_name != NULL)

strcpy(m_name, name);

m_age = age;

cout << m_name << endl;

}

Cperson::~Cperson()

{

cout << " 析构:"   <<  m_name << endl;

if(m_name != NULL)

delete m_name;

}

void Cperson::Print(void)

{

cout << "My age is " <<  m_age << " My name is " << m_name << endl;

}

void main(void )

{

Cperson Tom(10, "Tom");

Tom.Print();

Cperson Jim(Tom);

Jim.Print();

}

程序出现错误:

执行语句Cperson Tom(10, "Tom") 时,用new动态开辟了一段内存,用来存放"Tom"

执行Cperson Jim(Tom) 时只是将Tom 的成员Tom.m_age, Tom.m_name 赋值给了Jim 相应的成员。

此时 Tom.m_name   Jim.m_name 指向同一内存空间, 系统并没有给Jim.m_name开辟相应的内存空间。

执行完Jim.Print()后,开始执行析构函数,析构函数的执行顺序和构造函数的执行顺序相反,即先执行Jim的析构函数,释放掉Jim.m_name 的内存空间。析构Tom是空间就会出问题。


深拷贝:


class Cperson

{

public:

Cperson(int age, char *name);

Cperson(Cperson& per);

~Cperson();

void Print(void);

private:

int m_age;

char *m_name;

};

Cperson::Cperson(int age, char *name)

{

m_name = new char[strlen(name) + 1];

if(m_name != NULL)

strcpy(m_name, name);

m_age = age;

}

Cperson::Cperson(Cperson& per)

{

m_name = new char[strlen(per.m_name) + 1];

if(m_name != NULL)

strcpy(m_name, per.m_name);

m_age = per.m_age;

}

Cperson::~Cperson()

{

delete m_name;

}

void Cperson::Print()

{

cout << "My age is " << m_age << "My name is "<< m_name << endl;

}

void main(void)

{

Cperson Tom(10, "Tom");

Tom.Print();


Cperson Jim(Tom);

Cperson.Print();

}

自定义拷贝构造函数后,就没有问题了, 在实际中应尽量避免浅拷贝。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值