C++右值引用与移动操作

本篇博文主要记录C++ Primer第五版 13章《拷贝控制》6小节《对象移动》的相关知识点,主要回答右值引用的相关疑难点。

1. 右值引用类型

C++ Primer P471

在这里插入图片描述
在这里插入图片描述

右值引用与右值是两个不同的概念,所谓右值引用就是必须绑定到右值的引用。右值引用类型也是一种数据类型,因此可以定义右值引用类型的变量。由于右值引用只能绑定到临时对象,使用右值引用的代码可以自由地接管所引用的对象的资源。因此有个重要结论:我们不能将一个右值引用绑定到一个右值引用类型的变量上。

在这里插入图片描述

2. 右值是临时的,但不是不可修改的

C++ Primer P483
在这里插入图片描述

在旧标准中,我们没有办法阻止这种使用方式。为了维持向后兼容性,新标准库类仍然允许向右值赋值。

实际上,右值赋值分两种情况:
  (1)对内置基本数据类型的赋值;(2)对类类型的赋值。

(1)对于C/C++语言的内置基本数据类型,作为右值的场合下是不能被赋值的,也不可被修改。
在这里插入图片描述

(2)对于类类型的右值,该右值可以被赋值。对于类类型的右值,赋值的本质是右值进行一次函数调用(operator=);不论是类类型对象的属性是左值的或是右值的,const的或非const的,类类型的对象都是可以进行函数调用的。
在这里插入图片描述
如上,printstring()返回一个string临时对象,是右值;但是该右值可以调用函数(operator=)做赋值操作。同理,printdemo()返回一个demo类类型的临时对象,是右值;但是demo类型的operator=是删除的函数,所以没有赋值操作对应的函数,将报错。

在这里插入图片描述

现在把demo类中的operator=使用编译器合成的默认函数版本,则printdemo()返回的临时对象就可以进行赋值(operator=)的操作了。

结论:
  必须通过左值才能修改对象;除非这是一个class类型的对象,此时,在某些情况下也可以通过其右值修改该对象。[例:调用该对象的成员函数可以修改该对象。]
  s1+s2是右值,std::string是class类型,于是,可以通过成员函数std::string::operator=修改。int类型不是class类型,所以只能通过左值修改。

3. 左值引用与右值引用的函数重载

C++ Primer P482
在这里插入图片描述

要特别注意:我们不能将一个右值引用绑定到一个右值引用类型的变量上。

在这里插入图片描述

可以看到,对于类类型对象d1,传入左值d2和右值demo(10),分别调用demo类的operarot=(demo&)和operarot=(demo&&);然而,形参demo& 和 demo&& 调用的子类赋值函数都是拷贝赋值,而非移动赋值。因为右值引用类型的形参是一个局部变量,是左值而不是右值。

4. std::move标准库函数

要想解决第3点说的问题,需要使用std::move函数。

C++ Primer P472
在这里插入图片描述

在这里插入图片描述

可以看到,使用std::move标准库函数,可以把右值引用类型的变量当作右值使用。

C++ Primer P480
在这里插入图片描述

5. 左值右值引用限定符

C++ Primer P483
在这里插入图片描述

类似const限定符,引用限定符也是用来指定this的属性的。引用限定符可以是&或&&,分别指出this可以指向一个左值或右值。类似const限定符,引用限定符只能用于(非static)成员函数,且必须同时出现在函数的声明和定义中。

在这里插入图片描述
在这里插入图片描述

可以看到,sorted()函数重载了不同的版本,左值对象调用sorted() &版本,右值临时对象调用sorted() &&版本。

正如前面第2点,第3点所述,C++允许向类类型的右值赋值。要想阻止向类类型的右值赋值,除了定义删除的赋值运算符函数(operator=() = delete),还可以限制赋值运算符函数作用于左值this.

在这里插入图片描述

1.赋值函数定义了重载版本,包括拷贝版本和移动版本,因此可以有 f1 = f2; f1 = Foo();.
2.拷贝版本和移动版本都使用了引用限定符,指明赋值函数(operator=)的this都是左值属性,即赋值函数的this对象只能是左值,不能是右值.因此, Foo() = Foo(10);的调用将报错.

C++ Primer P483
在这里插入图片描述
在这里插入图片描述

有关右值引用的相关知识点暂时就说以上几点,如果想更深入了解,建议看看模板元编程相关的书籍,也建议去翻翻Boost库相关的书籍.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值