一文搞定移动语义和完美转发

本文深入探讨了C++中的移动语义和完美转发。移动语义通过右值引用实现资源的有效转移,避免不必要的拷贝,提高效率。文章讲解了浅拷贝和深拷贝的区别,移动构造函数如何利用移动语义,以及右值引用的概念。同时,还介绍了std::move和std::forward的使用,以及通用引用在实现完美转发中的作用。
摘要由CSDN通过智能技术生成

一文搞定移动语义和完美转发

浅拷贝和深拷贝

简单的区分: 浅拷贝:按字节拷贝,如果是指针变量则直接对指针地址进行拷贝 深拷贝:对内容进行拷贝,如果有指针变量则另外申请地址拷贝所指内容

写c++类时,如果类中有指针成员的话,通常我们都会格外注意,要注意拷贝构造函数的编写,因为如果简单的浅拷贝可能导致free一块未定义区域,是非法的。

如下面的程序:

#include<iostream>
using namespace std;
class HasPtrMem
{
   
public:
    HasPtrMem() :p(new int(0)) {
   }
    HasPtrMem(const HasPtrMem& h) :p(h.p) {
   }
    ~HasPtrMem() {
    delete p; }
    int* p;
};

int main()
{
   
    HasPtrMem a;
    HasPtrMem b(a);
    cout << *a.p << endl;
    cout << *b.p << endl;
}

构造函数申请了一块堆空间,而析构函数对该空间进行释放。在拷贝构造函数中,执行了浅拷贝,这会引发一个非常严重的问题:a的p申请了一块区域,对b执行了拷贝构造,则b的p指向了同一块区域,因此当程序执行结束时,a和b将纷纷执行其析构函数,假设a先执行其析构函数,则a将所指的区域进行了释放,那么释放后b的指针所指向的区域就成为了非法内存区域,即成为了dangling pointer 悬挂指针,对悬挂指针执行free释放内存将导致严重错误。

因此,通常我们会采用深拷贝的方法解决该问题:

#include<iostream>
using namespace std;
class HasPtrMem
{
   
public:
    int* p;
    HasPtrMem() :p(new int(0)) {
   }
    HasPtrMem(const HasPtrMem& h) :p(new int(*h.p)){
   }  //将拷贝构造函数改成深拷贝,重新申请一块堆上的内存,然后用h.p进行初始化
    ~HasPtrMem() {
    delete p; }
};

int main()
{
   
    HasPtrMem a;
    HasPtrMem b(a);
    cout << *a.p << endl;
    cout << *b.p << endl;
}

通过深拷贝,便可以解决浅拷贝的问题。使用深拷贝时,另外申请了一块区域并通过需要拷贝的对象的内容进行初始化,也就是其实指向的是不同的区域,只是内容相同。

看样子深拷贝完美解决了该问题,但是事实上确实这么完美吗?

移动语义

拷贝构造函数为指针成员进行内容拷贝的做法几乎是完美的,但是有些情况下该方法还是较为繁琐。下面的例子将说明:

#
  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值