美文网首页
右值引用的解释【1】

右值引用的解释【1】

作者: 家中古词 | 来源:发表于2018-12-05 19:17 被阅读10次

右值引用是 C++11 引入的特性,用来解决两个问题:

  1. 移动语义;
  2. 完美转发。

这一系列文章会从这解释这两个问题,并且从问题出发描述右值引用这种特性的特性和使用方法。

左值和右值

在 C 语言时代,可以放在等号左边的叫左值,只能放在右边的叫做右值。或者这根本是个结果论,是先有赋值的行为,然后将等号左边称作左值,不能赋值的就是右值。可以看出 C 语言中这个概念是很简单的。人们可以得到一系列认识:一个函数的返回值是右值,字面值表达式是右值等等。

但是 C++ 中,引用的出现,将这种简单的局面打破了。按照直觉来划分的内容面对用户自定义的类型产生的阴险修改和赋值行为,就不是十分合适了。正确的严格定义 C++ 中的左右值,可能是会有超出你预料的难度。这里我提出一种等效的定义:左值是可以使用 & 运算符来提取内存地址的表达式;而右值则是剩下的那些。

如果你对严格的定义感兴趣,可以参考 http://accu.org/index.php/journals/227

移动语义

当设计人员设计的类中含有一个引用资源的指针时(类似 std::vector),一个赋值运算符可能是这样写:

X &X::operator=(X const &other) const {
  // ...
  // make other_pointer a pointer of the clone of other.pointer;
  delete this->pointer;
  this->pointer = other.pointer;
  // ...
}

对于返回的 X 的函数、方法,查看这个例程:

X function_return_x();
X x;
// ...
x = function_return_x(); // #

# 处将返回的 x 克隆了一次,然后使 x 原本的资源析构,再让克隆本被 x 的指针管理;之后返回值就结束了作用域,所以它自己的资源也被释放。总之,释放了两份资源,新建(克隆)了一份资源:2-2+1 = 1。最后就只剩了 x 管理的资源。

这个行为是正确的,但是显然不太聪明。修改成 2-1 = 1 会让效率更高一点。也就是说将 x 的资源释放,返回值的资源直接送给 x 的指针管理。

更聪明的行为

我们设想的行为是这样的:

// ...
delete x.pointer;
x.pointer = other.pointer;
other.pointer = nullptr;
// ...

注意,第三步很重要,因为我们要假设这种情况里 other 马上要被析构了,所以要保证 other 指向的资源不要再它析构的时候被释放(这份资源已经归 x 所有)。

或者是这样的行为:

// ...
swap(x.pointer, other.pointer);
// ...

还是由于假设 other 一定马上要被析构,所以将 x 拥有的资源让给 other,资源就会被合理地释放。

上面两种行为虽然细节有不同,但是核心都是在对象之间转移资源。这种行为大致上就被称作移动语义。现在我们的目的就是探寻一种可以实现这种行为的语法,并且描述这种语法如何实现这种行为。

相关文章

网友评论

      本文标题:右值引用的解释【1】

      本文链接:https://www.haomeiwen.com/subject/lviwcqtx.html