美文网首页
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