所用的C++特性:右值引用
所用到的技术:移动语义
何谓移动语义:前提(所提及的指针是类内指针,且指向类内的动态内存分配操作的内存空间)
基于内存的思想,对于堆内存,总是会涉及到申请和释放;而有些时候我们并不需要当前的内存资源所存的数据立即被释放掉(此处延伸一下,对所谓的释放,我理解的是:堆内存空间被申请用来存放一定的数据,这块位置用完之后就要还给系统,即在堆内存的管理链表中重新被认定为空闲内存,里面的数据是否需要被清洗掉,此处不详,总之这块位置被归到空闲表中了),就是说,我这块空间暂时不想你被收回去(对于堆内存,只要你不主动释放,且始终有正确的指针指向它,系统会认为它一直是有效的非空闲的,因此才会引起“内存泄漏”,即老赖,“用了不还那种”),但是系统出于保护,往往会在限定的条件下自动调用析构函数,强制帮你释放掉当前指针所申请的这块内存,而在我们显示析构时,往往是在~A()中delete这个指针,即系统是根据这个指针(地址)以及它自身的类型(有类型才知道该收回多大空间啊,分配时同理)去完成回收工作的,因此,此时的移动构造技术实际上就是从这里切入的(因此我们需要从原理上去理解这个技术为什么而存在以及其合理性):我将当前对象的指针申请的这块空间绑定到另一个类对象的指针不就行了啊,而原指针也必然会被其所在的析构函数释放掉对应的资源,因此将其置为nullptr就太特么合理了!而新指针属于对象,也必然将被析构函数释放掉对应的内存。这招“偷天换日”就是移动构造的关键。
此处所举例的应用背景是:返回一个局部变量(自定义类型),对于临时对象的资源使用移动构造函数代替复制构造函数完成其对应的功能,可以减少一次深拷贝操作(这对于大容量的堆内存复制是非常有效的)。
解释:
上图中,getNum()函数中需要返回的是一个局部变量,因此它此时就是一个临时变量,因为在函数结束后它就消亡了,对应的其动态内存也会被析构掉,所以系统在执行return函数之前,需要再生成一个临时对象将a中的数据内容返回到被调的主函数中,此处自然就有两种解决方法:1、调用复制构造函数进行备份;2、使用移动构造技术把即将消亡的且仍需要用到的这部分内存的所有权进行转移,手动延长它的生命周期。
显然,前者需要深拷贝操作依次复制全部数据,而后者只需要“变更所有权”即可。
此处更需要说明的是:遇到这种需求时,编译器会很智能帮你选择类内合适的构造函数去执行,如果没有移动构造函数,它只能默认的选择复制构造函数,而同时存在是自然会优先选择移动构造函数。