美文网首页
c++右值引用

c++右值引用

作者: TimeMage | 来源:发表于2019-10-15 17:18 被阅读0次

右值引用是什么,把它拆开来说,首先是个引用,即一个变量的绑定或别名。然后这个变量是右值,可以理解为临时变量。
右值是什么,在赋值表达式右端通过计算产生的中间结果或字面量。比如int c =a+b, a+b即为右值,它会产生个a+b的临时变量,然后通过拷贝赋值给c, 这个临时变量随后就会被销毁,但是如果使用右值引用捕获,它就会像左值一样继续延续下来。比如int&& a = a+b。所以右值引用,是右值的引用,的表从属关系。
右值引用不能捕获左值,但对于闲置的左值,可以通过std::move转换成右值。然后被右值引用捕获。
右值引用最大的作用是语义上的,它表明自身引用的是闲置变量,因此可以把这个引用里的资源挪走用于他处,但要是显式的(比如通过移动构造函数)。而左值引用更关注的是把它修改。
移动构造函数和移动赋值函数使用右值引用捕获右值,从而达到定义和赋值变量时减少资源拷贝的目的。

代码示例

#include <cstdio>
#include <vector>
#include <iostream>
#define dbg(x) std::cout << #x ": " << x << std::endl;

std::ostream &operator<<(std::ostream &out, const std::vector<int> &v) {
  bool first = true;
  for (auto e : v) {
    if (!first) {
      out << ",";
    }
    out << e;
    first = false;
  }
  out << std::endl;
  return out;
}
void test_move() {
  puts("test_move");
  std::vector<int> v{1, 2, 3};
  dbg(v); // 1 2 3
  std::vector<int> w(
      std::move(v)); // 将左值转换成右值, 然后再通过移动构造函数,转移资源
  dbg(v); // v:
  dbg(w); // w: {1 ,2, 3}
  int a = 1;
  int b = std::move(a); // int 类型不支持移动构造, 无法转移资源
  dbg(a);               // a: 1
  dbg(b);               // b: 1
}
void test_lref() {
  puts("test_lref");
  std::vector<int> &&r = std::vector<int>{1, 2, 3}; //右值引用绑定右值
  dbg(r);                                           // 1 2 3
  std::vector<int> x(
      r); // 命名的右值引用是左值,表明虽然引用的是闲置资源,但仍然需要显示移动资源
  dbg(r); // 1 2 3
  dbg(x); // 1 2 3
  std::vector<int> v;
  v = static_cast<std::vector<int> &&>(
      x); // 未具名的右值引用为右值,比如move,或static_cast<std::std::vector<int>&&>
  dbg(v); // 1 2 3
  dbg(x); //
}
void test_lref_sim() {
  puts("test_lref_sim");
  int &&a = 1; // 右值可以看作临时变量, 右值引用延续临时变量的生命
  dbg(a);                        // a 1
  printf("address a: %p\n", &a); // address a: 0x7ffee87ab6bc
  int &&b = 1;
  dbg(b);                        // b 1
  printf("address b: %p\n", &b); // address b: 0x7ffee87ab6ac
  int &&c = a + 0;
  dbg(c); // c 1
  const int &d = 1;
  printf("address d: %p\n", &d); // 常量左值引用都可绑定,只是无法修改
  // int &&c = a;   左值不能直接赋值给右值引用
  int x = 12;
  int &&y = std::move(x); // 右值引用是个引用
  y = 13;
  dbg(x); // 13
  dbg(y); // 13
}
int main() {
  test_lref_sim();
  test_lref();
  test_move();
  return 0;
}

相关文章

网友评论

      本文标题:c++右值引用

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