C++:右值引用 && 和移动赋值std::move分析

右值引用

左值:赋值号左边,可以取地址

  • 变量名
  • 返回左值引用的函数调用
  • 前置自增,前置自减:++i;–i;
  • 赋值运算

右值:赋值号右边,不可以取地址;将亡值,通常是将要被移动的对象

  • 常量
  • 返回非用类型的函数调用
  • 后置自增:i ++
  • 算术表达式 (a+b)
  • 逻辑表达式(a && b)…
  • std::move() 移动的值
  • 被右值引用的值
定义:

如,将func() 返回类对象赋值给类A的对象a
A && a = func();
功能:调高使用临时对象的效率

code:

分析:
发生1次构造,1次拷贝构造:
第一次构造为getObjectA()中A()的构造
1次拷贝构造为将A() 赋值给临时对象,
临时对象申请的空间赋值给对象a 没有发生拷贝行为,提高了效率

class A
{

public:
    A(){
        cout<<"A() "<<this<<endl;
    }
    ~A(){
        cout<<"~A() "<<this<<endl;
    }
    A(const A &another)
    {
        cout<<"A(const A&)"<<&another<<"->"<<this<<endl;
    }
};
A getObjectA()
{
    return A();
}
int main()
{
    A && a = getObjectA(); 
    return 0;
}
运行结果:
A() 
A(const A&)
~A() 
~A() 

移动赋值

语义:对象赋值时,避免内存空间的重新分配

定义:

如, 将类A 对象a 移动赋值给 对象b
A b(std::move(a));

功能:提高将类对象返回值赋值给临时对象的效率

code (包含自实现类中的6大默认):
类对象的移动构造

分析:
一次构造,一次移动构造
一次构造为 a对象的构造
移动构造为 将 a 赋值给b, a所申请的空间没有进行拷贝,提高了效率

class Move
{
public:
    Move(int i = 0):_i(new int(i))
    {
        cout<<"Move()"<<endl;
    }

    Move(const Move & another)
        :_i(new int(*another._i))
    {
        cout<<" Move(const Move & another)"<<endl;
    }

    Move & operator=(const Move & another)
    {
        cout<<" Move & operator=(Move & another)"<<endl;

        if(this != &another)
        {
            delete _i;
            _i = new int(*another._i);
        }
        return *this;
    }


    Move( Move && another)
    {
        cout<<" Move( Move && another)"<<endl;
        _i = another._i;
        another._i = nullptr;
    }
    Move & operator=(Move && another)
    {
        cout<<" Move & operator=(Move && another)"<<endl;
        if(this != &another)
        {
            delete _i;
            _i = another._i;
            another._i = nullptr;
        }
        return *this;
    }
    ~Move()
    {
        if(_i != nullptr)
            delete _i;
        cout<<"~Move()"<<endl;
    }
    int *_i;
};


int main(int argc, char *argv[])
{
    //拷贝构造(深拷贝),若不自实现拷贝构造,则报错
//    Move m;
//    Move n(m);

    //拷贝赋值
//    Move p;
//    Move q;
//    q = p;

    //移动构造
    Move a;
    Move b(std::move(a));  //std::move() 将左值变为右值,m为将亡值

    // 移动赋值
//    Move c;
//    Move d;
//    d =(std::move)(c);


    return 0;
}
运行结果:
Move()
Move( Move && another)
~Move()
~Move()
类成员对象的移动构造

分析:
若要实现类Moveable 成员对象Complex _c的移动构造,需要在类Moveable的构造函数中使用std::move移动_c对象,可以避免类Moveable的对象赋值时,类成员对象_c所申请空间的拷贝,提高了效率

#include <iostream>

using namespace std;

class Complex
{
public:
    Complex(int f = 0)
        :_f(new float(f))
    {
        cout<<"Complex()"<<endl;
    }
    Complex(const Complex & another)
        :_f(new float(*another._f))
    {
        cout<<"Complex(const Complex & another)"<<endl;
    }
    Complex(Complex && another)
        :_f(another._f)
    {

        another._f = nullptr;
        cout<<" Complex(Complex && another)"<<endl;
    }
    Complex& operator = (const Complex & another)
    {
        cout<<"Complex& operator = (const Complex & another)"<<endl;
        if(this != &another)
        {
            delete _f;
            _f = new float;
            *_f = *another._f;
        }
        return *this;
    }
    Complex& operator = ( Complex && another)
    {
        cout<<" Complex& operator = (const Complex && another)"<<endl;
        if(this != &another)
        {
            delete _f;
            _f = another._f;
        }
        return *this;
    }
    ~Complex()
    {
        if(_f != nullptr)
            delete _f;
    }
    float *_f;
};
class Moveable
{
public:
    Moveable(int i)
        :_i(new int(100)),_c(2.1) //先父类,再类对象,再本类
    {
        cout<<" Moveable(int i)"<<endl;
    }
    Moveable(const Moveable &another )
        :_i(new int(*another._i))
        ,_c(another._c)
    {
        cout<<" Moveable(const Moveable &another )"<<endl;
    }
    Moveable(Moveable &&another)
    {
        cout<<" Moveable(Moveable &&another)"<<endl;
        _i = another._i;
        another._i = nullptr;
        _c = std::move(another._c); //走 Complex 移动赋值
    }
    ~Moveable()

    {
        if(_i != nullptr)
            delete _i;
    }
    int *_i;
    Complex _c; //类对象成员
};
int main(int argc, char *argv[])
{
    Moveable m(100);
    Moveable n(std::move(m)); //走移动构造
    return 0;
}
运行结果:
Complex()
Moveable(int i)
Complex()
Moveable(Moveable &&another)
Complex& operator = (const Complex && another)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

八月的雨季997

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值