4.移动构造函数

0.左值和右值

简单来说,左值用的是它的内存空间,右值用的是它的内容(值)。所以,左值和右值不能简单的凭借在等号的左右边来进行判断,只不过很常见的一种情况是,等号左边的是左值,等号右边的是右值。
通常来说,左值的类型有:指针,变量。右值的类型有:临时对象,常量。

int num1 = 6;
int num2 = num1;

比如这里的num1,在第一条语句的时候是作为左值,用的是num1的一个内存空间,来存放一个临时对象的值,然后在第二条语句的时候num1是作为右值,用的是它的内容,来存放到num2的地址处。
这和移动构造函数有什么关系呢,拷贝构造函数,默认构造函数,亦或是赋值函数,用的都是左值,也就是直接使用的是内存空间,而移动构造函数用的则是右值,用的是它的具体的值。

1.拷贝构造函数

1.浅拷贝构造函数,浅拷贝在遇到指针作为属性时,在构造的时候是简单赋值,然后会存在二次释放内存空间的问题。
2.深拷贝构造函数,深拷贝的出现就是为了不再是简单的赋值,而是重新申请空间,将内存空间的属性的值一一赋给新对象,这样的话两个对象就都有了自己的一块内存来存放数据。自然也不会有重复释放同一块内存空间的情况了。具体区别及代码可参见上篇博客:3.类的构造函数、析构函数、赋值函数、拷贝函数

问题来了:深拷贝需要每次新申请一块空间,这在类里面的数据占用空间较小的情况也是没问题的,但是占用数据大了之后,频繁的深拷贝无疑是对性能的浪费,所以我们开始考虑移动构造函数了。

2.移动构造函数

所以的话移动构造函数出现了,为了解决深拷贝新开辟空间的问题,现在的话直接将旧对象内存空间的起始地址给了新对象,然后旧对象的内存空间起始位置置为NULL。这样的话就相当于不用一一拷贝了,直接就把内存空间的数据给新对象了,旧对象的内存空间的数据就没了。因为右值的话很多时候是临时对象,它们并不需要再接着使用。
语法上的区别是在引用的基础上多了一个&。
我们知道,非 const 右值引用只能操作右值,程序执行结果中产生的临时对象(例如函数返回值、lambda 表达式等)既无名称也无法获取其存储地址,所以属于右值。当类中同时包含拷贝构造函数和移动构造函数时,如果使用临时对象初始化当前类的对象,编译器会优先调用移动构造函数来完成此操作。只有当类中没有合适的移动构造函数时,编译器才会退而求其次,调用拷贝构造函数。

3.浅拷贝和移动构造函数

在我理解的一段时间,我都会有这样的疑惑,浅拷贝虽然是指针的拷贝,会出现二次释放内存空间的问题,但是只要将旧对象的指针置为NULL,那么旧对象的释放就没处释放了。但是这样出现的问题是:由于是左值,很多时候并不是一个临时对象或者叫将亡值,也就是这个对象还有用,不能轻易的释放它。那么移动构造函数由于是右值引用,很多时候都是即将在栈区被释放的内存,移动构造函数把这部分内存拿过来,延长了它的一个生命周期,把原有的指针变量置为NULL。
参考博客:http://m.biancheng.net/view/7847.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值