C++ 移动构造函数和拷贝构造函数

 

  1. 我们用对象a初始化对象b,后对象a我们就不在使用了,但是对象a的空间还在呀(在析构之前),既然拷贝构造函数,实际上就是把a对象的内容复制一份到b中,那么为什么我们不能直接使用a的空间呢?这样就避免了新的空间的分配,大大降低构造的成本。这就是移动构造函数设计的初衷;
  2. 拷贝构造函数中,对于指针,我们一定要采用深层复制,而移动构造函数中,对于指针,我们采用浅层复制浅层复制之所以危险,是因为两个指针共同指向一片内存空间,若第一个指针将其释放,另一个指针的指向就不合法了。所以我们只要避免第一个指针释放空间就可以了。避免的方法就是将第一个指针(比如a->value)置为NULL,这样在调用析构函数的时候,由于有判断是否为NULL的语句,所以析构a的时候并不会回收a->value指向的空间;
  3. 移动构造函数的参数和拷贝构造函数不同,拷贝构造函数的参数是一个左值引用,但是移动构造函数的初值是一个右值引用。意味着,移动构造函数的参数是一个右值或者将亡值的引用。也就是说,只用用一个右值,或者将亡值初始化另一个对象的时候,才会调用移动构造函数。而那个move语句,就是将一个左值变成一个将亡值

浅复制 

#include<iostream>
#include<vector>
using namespace std;

class Test
{
public:
	Test(int num,char *ptr) 
	{
		x = num; p = ptr;
		cout << "构造函数"<<endl;
	}
	Test(const Test& a) :x(a.x),p(a.p)  //浅复制
	{
		cout << "拷贝构造函数" << endl;
	}
	Test(Test&& a) : x(a.x)
	{
		p = a.p;
		a.p = NULL;
		cout << "移动构造函数" << endl;
	}
	~Test()
	{
		if (p != NULL)
			delete p;
	}
private:
	int x;
	char *p;
};

int main()
{
	int x = 8;
	char ch = 'A';
	Test a(x,&ch);
	Test b(a);
	Test c(move(a));

	return 0;
}

输出:

构造函数
拷贝构造函数
移动构造函数

b.p和c.p指向同一个内存,因为都是浅复制。有指针成员变量时,拷贝构造函数要深复制(自动生成的拷贝构造函数是浅复制)

深复制

#include<iostream>
#include<vector>
using namespace std;

class Test
{
public:
	Test(int num,char *ptr) 
	{
		x = num; p = ptr;
		cout << "构造函数"<<endl;
	}
	Test(const Test& a) :x(a.x)
	{
		p = new char(1);    //深复制
		*p = *(a.p);
		cout << "拷贝构造函数" << endl;
	}
	Test(Test&& a) : x(a.x)
	{
		p = a.p;
		a.p = NULL;
		cout << "移动构造函数" << endl;
	}
	~Test()
	{
		if (p != NULL)
			delete p;
	}
	int x;
	char *p;
};

int main()
{
	int x = 2;
	char ch = '%';
	char*p = &ch;
	cout << (void *)p << endl; //输出指针的值要用void*
	Test a(x,p);
	Test b(a);
	Test c(move(a));

	return 0;
}

b的p成员的值与a不同,c的p值与a.p相同

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值