《C++ Primer》读书笔记第十三章-3-对象移动

笔记会持续更新,有错误的地方欢迎指正,谢谢!

对象移动

移动对象的优势:

  1. 我们在赋值操作时,对象拷贝后就立即销毁,但移动而非拷贝对象会大幅度提升性能。
  2. 有些类型是不能被拷贝的,如IO类和unique_ptr,在旧标准中我们无法在容器中保存它们,因为它们无法被拷贝,就不存在赋值之类的操作。但引入了移动操作后,我们就可以用容器保存它们。

右值引用

通过&&来获得右值引用,右值引用只能绑定到一个即将销毁的对象上,所以,我们才能自由地将一个右值引用的资源移动到另一个对象中。

记住左值长期存在的;右值是临时的,是即将销毁的。也就是左值持久,右值短暂
右值要么是字面常量,要么是求值过程中创建的临时对象。
来看几个例子:

int i = 42;
int &r = i; //对
int &&rr = i; //错,右值不是字面常量,也不是临时对象
int &r2 = i * 24; //错,不能把临时对象赋给普通引用
const int &r3 = i * 13; //对,可以把临时对象赋给引用常量
int &&rr2 = i * 2; //对,右值是临时对象
int &&rr3 = 42; //对,右值是字面值常量
int &&rr4 = rr3; //错,绑定右值引用的变量rr3仍是左值,即rr3是正常的变量。

右值引用只能绑定到临时对象的原因:

  1. 所引用的对象将要被销毁
  2. 该对象没有用户

所以,使用右值引用的代码可以自由地接管所引用的对象的资源。

标准库move函数

强行右值,move算是一个移动构造函数:

int a = 12;
int &&b = std::move(a) //move函数告诉编译器,要把这个左值a当右值处理。

调用move就意味着:除了对a赋值或销毁外,我们将不再使用它,例如我们不能把它的值赋给别人。

移动构造函数

类似对应的拷贝操作,但它从给定对象窃取资源而不是拷贝资源。
移动构造函数和拷贝构造函数的唯一区别就是它的引用是右值引用。
一旦资源完成移动,原对象必须不再指向被移动的资源,所有权已归属新对象。

用老朋友StrVec定义移动构造函数(它没有分配新内存):

StrVec::StrVec(StrVec &&s) noexcept : elements(s.elements),
first_free(s.first_free), cap(s.cap) //noexcept表示不抛出异常
//noexcept:声明和定义不抛出异常的移动构造函数和移动赋值函数都要显式
//指定noexcept,否则系统会使用拷贝操作。
{
    //上面的列表初始化就移动好了,注意第一个参数是非const右值引用
    //接下来的话保证s进入这样的状态-对其进行析构函数是安全的
    s.elements = s.first_free = s.cap = nullptr;
}

其实就是s把资源给了新对象,自己都变成空指针,深藏功与名了。

移动赋值运算符

类似对应的拷贝操作,但它从给定对象窃取资源而不是拷贝资源。

和赋值运算符类似,也要正确处理自赋值情况:

StrVec &StrVec::operator=(StrVec &&rhs) noexcept
{
    if(this != &rhs) //检测,不是自赋值再进行下面步骤,是自赋值直接返回
    {
        free(); //因为它要接管rhs,原来的内存就不用了。
        //从rhs窃取资源
        elements = rhs.elements;
        first_free = rhs.first_free;
        cap = rhs.cap;

        //将rhs置于可析构状态
        rhs.elements = rhs.first_free = rhs.cap = nullptr;
    }
    return *this;
}

移后原对象要保持有效的,可析构的状态,但最好不要去动它,除了析构它之外,让它安静地功成身退。

合成的移动操作

没有任何自定义的拷贝控制成员,且每个非stastic数据成员都可以移动时,编译器才会为他们合成移动构造函数或移动赋值运算符。

移动和拷贝

编译器使用普通的函数匹配规则确定使用哪个拷贝控制成员。通常,拷贝左值,移动右值。如果没有移动构造函数,右值也被拷贝。

移动迭代器

通过标准库的make_move_iterator函数来将普通迭代器转换为移动迭代器。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值