美文网首页
C++的lvalue, rvalue, rvalue refer

C++的lvalue, rvalue, rvalue refer

作者: 尚无花名 | 来源:发表于2019-12-16 12:09 被阅读0次

    神秘的C++, 这就是C++的一个神秘之处。这是什么?? 我也是很抓狂。

    Left Value: 左值:

    something you can assign to.
    在赋值操作的左边;
    可以是address (&foo).
    如果它有一个名字,then it is left value.
    refer to 一个内存地址,允许我们用&取地址。

    Right value:

    Something you can't assign to.
    如临时变量;temporary object returned by value;
    出现在赋值操作的右边。
    An rvalue is an expression that is not an lvalue.

    int& foo();
    int* r = &foo(); // 可以, 因为foo返回的是一个reference, 是一个左值, 可以取地址
    int bar();
    int* r = &bar(); //不可以,因为bar()返回的是一个rvalue,不能取地址。
    

    rvalue reference:

    X& is a lvalue reference.
    X&& is a rvalue reference.
    Rvalue reference就是对一个无名小卒的reference。

    void foo(X& x);
    void foo(X&& x);
    X x;
    X foobar();
    foo(x); // 左值引用
    foo(foobar()); // 右值引用 
    

    这里foo函数被overload. 可以是X& x 的输入,也可以是X&&的输入。
    虽然可以任意设计这些overload, 但这样的overload应该之发生在copy和assignment operator上。别的函数不要乱来。

    所以这...有什么用呢,说了半天浪费我时间吗?

    我们为什么需要知道右值引用呢?
    R value reference 可以用来实现move semantics和perfect forwarding
    Perfect forwarding改日再说.
    Move Semantics主要是用来解决copy constructor和assignment operator(=)虚耗的。
    okay. 你说move semantics很Diao我不质疑, 可是为什么要用R value reference?
    因为compiler很胆小,只敢欺负Rvalue reference这样的无名小卒, 没有r value reference compiler不敢用move semantics。

    比如

    MyClass x;
    MyClass foo();
    x = foo();
    

    如果没有move semantics, 则foo产生的Object会被Copy一下,再assign给x. 如果有了move semantics, 则foo() return的 那个object 可以直接丢给x, 把reference 本身copy一下就好了。 x 原来的那个就直接丢掉了。
    这样就要求 MyClass的operator= 需要能接受 rvalue reference(), 因为 x = foo()的右边是个右值。
    所以 MyClass 要有一个operator overload

    MyClass& operator=(MyClass&& rhs) {
      // move semantics
      return *this;
    } 
    

    如果还有一个 operator= overload

    MyClass& operator=(MyClass& lhs) {
      // 这是一个左值引用
    }
    

    那对于两个overloaded的operator=, 一个是左值引用的,一个是右值引用的, compiler怎么选呢?compiler怎么知道用哪一个?
    if it has a name, then it is an lvalue. Otherwise, it is an rvalue。 通俗说就是无名小卒。
    Move semantics只用来处理那些compiler确定是用完就扔的object, compiler谨小慎微怕出错。
    只敢对付无名小卒,但凡有名有姓的,都怕程序员会惦记,不敢碰。

    那如果非要用选用右值引用的怎么办?如果我有两个变量 a, b;

    MyClass a, b;
    

    如果我想把b转移给a, 让 a = b,
    但是 这时compiler会自动选左值引用的 operator=, 没法实现move semantics.
    这时 用a = std::move(b) , std::move(b)的返回值就是一个无名小卒。所以强制compiler用右值引用的。这程序员自已把b打成无名小卒,然后丢给compiler说你把它当右值引用。当然程序猿您以后可别惦记b。

    相关文章

      网友评论

          本文标题:C++的lvalue, rvalue, rvalue refer

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