C++11 rvalues and move semantics confusion (return statement)

前端 未结 6 1279
死守一世寂寞
死守一世寂寞 2020-11-22 04:29

I\'m trying to understand rvalue references and move semantics of C++11.

What is the difference between these examples, and which of them is going to do no vector cop

6条回答
  •  暗喜
    暗喜 (楼主)
    2020-11-22 05:01

    As already mentioned in comments to the first answer, the return std::move(...); construct can make a difference in cases other than returning of local variables. Here's a runnable example that documents what happens when you return a member object with and without std::move():

    #include 
    #include 
    
    struct A {
      A() = default;
      A(const A&) { std::cout << "A copied\n"; }
      A(A&&) { std::cout << "A moved\n"; }
    };
    
    class B {
      A a;
     public:
      operator A() const & { std::cout << "B C-value: "; return a; }
      operator A() & { std::cout << "B L-value: "; return a; }
      operator A() && { std::cout << "B R-value: "; return a; }
    };
    
    class C {
      A a;
     public:
      operator A() const & { std::cout << "C C-value: "; return std::move(a); }
      operator A() & { std::cout << "C L-value: "; return std::move(a); }
      operator A() && { std::cout << "C R-value: "; return std::move(a); }
    };
    
    int main() {
      // Non-constant L-values
      B b;
      C c;
      A{b};    // B L-value: A copied
      A{c};    // C L-value: A moved
    
      // R-values
      A{B{}};  // B R-value: A copied
      A{C{}};  // C R-value: A moved
    
      // Constant L-values
      const B bc;
      const C cc;
      A{bc};   // B C-value: A copied
      A{cc};   // C C-value: A copied
    
      return 0;
    }
    

    Presumably, return std::move(some_member); only makes sense if you actually want to move the particular class member, e.g. in a case where class C represents short-lived adapter objects with the sole purpose of creating instances of struct A.

    Notice how struct A always gets copied out of class B, even when the class B object is an R-value. This is because the compiler has no way to tell that class B's instance of struct A won't be used any more. In class C, the compiler does have this information from std::move(), which is why struct A gets moved, unless the instance of class C is constant.

提交回复
热议问题