C++11 rvalue reference vs const reference

后端 未结 5 1183
你的背包
你的背包 2020-12-06 02:54

This may be obvious but I think it is something difficult to me. Given this:

void test(std::string&&) { }

std::string x{\"test\"};
test(std::move(x)         


        
相关标签:
5条回答
  • 2020-12-06 03:20

    In simple terms:

    • && can bind to non-const rvalues (prvalues and xvalues)
    • const && can bind to rvalues (const and non-const)
    • & can bind to non-const lvalues
    • const & can bind to rvalues (prvalues and xvalues) and lvalues (const and non-const for each). A.k.a. to anything.
    0 讨论(0)
  • 2020-12-06 03:29

    If you want a function to expressly allow const-Lvalue objects, but expressly disallow Rvalue objects, write the function signature like this:

    void test(const std::string&) { }
    void test(std::string&&) = delete;//Will now be considered when matching signatures
    
    int main() {
        std::string string = "test";
        test(string);//OK
        //test(std::move(string));//Compile Error!
        //test("Test2");//Compile Error!
    }
    
    0 讨论(0)
  • 2020-12-06 03:39

    When you call std::move(x), an rvalue reference to the underlying data, test, will be returned. You are allowed to pass rvalue references as const (and const only!) reference parameters because an rvalue reference is implicitly convertible to a const reference. They are arguably the same thing from the function's point of view (a read only parameter). If you removed the const-qualifier of your parameter, this code would not compile:

    void other_test(std::string&) { }
    std::string x{"test"};
    other_test(std::move(x)); //not okay because
    //the function can potentially modify the parameter.
    

    See Bo Qian's youtube video on rvalue vs lvalue.

    0 讨论(0)
  • 2020-12-06 03:41

    std::move doesn't actually move anything out of it's own. It's just a fancy name for a cast to a T&&. Calling test like this test(std::move(x)); only shows that a T&& is implicitly convertible to a const T&. The compiler sees that test only accepts const T& so it converts the T&& returned from std::move to a const T&, that's all there is to it.

    0 讨论(0)
  • 2020-12-06 03:47
    test(std::string&& a) {
      something(a) //--> not moved because it has lvalue
    

    Names of variables are lvalues. a is a name of a variable, therefore a is an lvalue expression, and therefore it will not be moved from.

    It's unclear what you mean by "has". a is an expression. It is a name of a reference, and references refer to objects. Value categories pertain to expressions, not objects.

    test(const std::string& a): a is const lvalue reference and like before I have lvalue and rvalue. And plus more, in this case if I called

    std::move(a)
    

    where a is a const& the move works!

    If by "works" you mean that it invokes a move constructor or assignment, then no, it does not work because no move construction or assignment has happened.

    0 讨论(0)
提交回复
热议问题