右值引用,移动构造,移动赋值

1、目的

右值引用,移动构造和移动赋值是在C++11中引入的,其目的是为了提升代码效率

2、使用场景

类中如果有需要申请动态资源的成员,那么定义移动构造函数和移动赋值运算符可以避免不必要的拷贝工作,从而提升代码效率。移动构造和移动赋值并不会新开辟资源,而是将源对象的一部分或全部资源移交给了新对象。std::move()的作用是将一个左值转换为右值,但它并没有进行真正的内存移动操作。

3、代码举例
class A
{
public:

    A(int a):a_(a),vp(std::vector<int>(1000000))
    {
        for(int i=0;i<vp.size();i++)
        {
            vp[i] = i;
        }
        std::cout<<vp.size()<<std::endl;
    }

    A(A &&tmpA)//移动构造函数
    {
        if(this != &tmpA)
        {
            a_ = tmpA.a_;
            std::cout<<&(tmpA.vp[0])<<std::endl;//这里打印了一下tmpA.vp[0]的地址是为了说明是是否发生了拷贝
            vp.clear();
            vp = std::move(tmpA.vp);
            
        }
        std::cout<<"移动构造函数"<<&(vp[0])<<" "<<vp.size()<<" "<<tmpA.vp.size()<<std::endl;
    }
    
	A& operator=(A &&tmpA)
    {
        if(this != &tmpA)
        {
            a_ = tmpA.a_;
            vp.clear();
            vp = std::move(tmpA.vp);
        }
        std::cout<<"移动赋值"<<std::endl;
        return *this;
    }

    A(const A &tmpA)//拷贝构造函数
    {
        if(this != &tmpA)
        {
            a_ = tmpA.a_;
            std::cout<<&(tmpA.vp[0])<<std::endl;
            vp.clear();
            vp.assign(tmpA.vp.begin(),tmpA.vp.end());
        }
        std::cout<<"拷贝构造函数"<<&(vp[0])<<" "<<vp.size()<<" "<<tmpA.vp.size()<<std::endl;
    }


private:
    int a_;
    std::vector<int> vp;
};

int main()
{
    std::chrono::steady_clock::time_point start_time;
    std::chrono::steady_clock::time_point end_time;
    
    A a1(10);

    start_time = std::chrono::steady_clock::now();
    A a2(a1);
    end_time = std::chrono::steady_clock::now();
    std::chrono::duration<double> diff = end_time-start_time;
    std::cout<<"拷贝构造耗时:"<<diff.count()*1000<<"ms"<<std::endl;


    start_time = std::chrono::steady_clock::now();
    A a3(std::move(a1));
    end_time = std::chrono::steady_clock::now();
    diff = end_time-start_time;
    std::cout<<"移动构造耗时:"<<diff.count()*1000<<"ms"<<std::endl;
    
    

    return 0;
}

打印的log如下:

1000000
0x7fec1db5e010
拷贝构造函数0x7fec1d78d010 1000000 1000000
拷贝构造耗时:2.37644ms
0x7fec1db5e010
移动构造函数0x7fec1db5e010 1000000 0
移动构造耗时:0.004215ms
移动赋值

从log上看出拷贝构造函数发生了实际的内存拷贝,源对象依旧有效,新对象是在新的内存地址上的一个对象,只是内容与源对象相同。而移动构造函数新对象的vp成员接管了源对象的vp成员的内存,没有发生内存复制,从打印的vp[0]的地址可以看出新对象的vp[0]地址与源对象的vp[0]地址相同,说明没有复制内存,但移动构造后源对象中的vp.size()变成了0,说明源对象已经失去了那块内存所有权。

从打印的耗时上看,移动构造要比拷贝构造快很多,这和拷贝的数据量多少有关。
另外,调用移动构造函数后,不因该对源对象做任何假设,源对象不能再使用了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值