C++:类3-对象移动、移动构造、移动赋值

某些情况下,对象拷贝后就会立即被销毁,此时,移动而非拷贝对象会大幅度提升性能

右值引用(rvalue reference)

int i = 42;
int &&r = i * 42;   //将右值引用绑定到一个右值上
  • 返回左值引用的函数,赋值,下标,解引用,前置递增/递减运算符->返回左值。
  • 返回非引用类型的函数,算术,关系,位,后置递增/递减运算符->返回右值。
  • 左值表示一个对象的身份,而一个右值表示对象的值。
  • 右值引用只能绑定到临时对象上去
  • 右值引用指向即将被销毁得分对象。来移动对象。
  • 用右值引用来表示移动语义->定义移动构造函数,移动赋值运算符

标准库move函数

  • std::move® 获得绑定到左值上的右值引用。
  • 调用move就意味着:除了对它进行赋值或销毁它外,不再使用它。
  • 注意:应使用std::move而不是move

移动构造函数

Foo::Foo(Foo &&rhs) noexcept    //禁止其抛出异常
{
    ptr1_member = rhs.ptr1_member;
    ptr2_member = rhs.ptr2_member;
    
    //将rhs置于可析构状态
    rhs.ptr1_member = rhs.ptr2_member = nullptr;
}

移动赋值运算符

Foo &Foo::operator=(Foo &&rhs) noexcept
{
    if(this != &rhs){
        free();         //释放已有元素
        ptr1 = rhs.ptr1;
        ptr2 = rhs.ptr2;
        
        //将rhs置于可析构状态
        rhs.ptr1 = rhs.ptr2 = nullptr;
    }
    
    return *this;
}
  • 完成资源移动后,源对象必须不再指向被移动的资源。
  • 完成移动操作后,移后源对象必须保持有效的(可以安全地为其赋予新值或可以安全地使用而不依赖其当前值)、可析构的状态,但是用户不能对其值进行任何假设。
  • 不抛出异常的移动构造函数和移动赋值运算符需标记为noexcept。

合成的移动操作

  • 编译器合成移动构造函数/赋值运算符的条件:
    • 类没有自己版本的拷贝控制成员
    • 类的每个非static数据成员都可以移动
  • 如果类定义了一个移动构造函数和/或一个移动赋值运算符,则该类的合成拷贝运算符和拷贝赋值运算符会被定义为删除的。

移动右值,拷贝左值。若没有移动构造函数,右值也被拷贝。

拷贝并交换赋值运算符

Foo& Foo::operator=(Foo rhs){
    swap(*this, rhs);
    return *this;
}
  • 即实现了拷贝赋值运算符,也实现了移动赋值运算符。

移动迭代器(move iterator)

  • make_move_iterator函数将一个普通迭代器转换为一个移动迭代器。
  • 对其解引用返回右值引用。
  • 标准库不保证那些算法使用移动迭代器。

为成员函数同时提供拷贝版本和移动版本

void push_back(const X&);   //拷贝
void push_back(X&&);        //移动

区分调用成员函数的对象是左值还是右值

  • 在参数列表后放置一个引用限定符(reference qualifier), & 或 &&。
Foo &Foo::operator=(const Foo &rhs) &   //加一个&,限定只有左值可以调用该函数,即限制只可以赋值给左值
{
    //执行赋值操作...
    
    return *this;
}
  • &限制只能用于左值
  • &&限制只能用于右值
  • 右const时,放在const之后

综合const和引用限定符来重载函数

class Foo{
    public:
        //&&:用于右值的版本
        Foo sorted() &&
        {
            //对象本为右值,可以原址排序
            sort(data.begin(), data.end());
        }
        
        //可以用于任何类型
        Foo sorted() const &
        {
            Foo ret(*this);
            sort(ret.data.begin(), ret.data.end());
            return ret;
        }
        
    private:
        DATA data;
    
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

绫零依

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

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

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

打赏作者

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

抵扣说明:

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

余额充值