Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reason to use std::move on rvalue reference parameter

I was reading a book about data structure implemented in C++, I dont understand a code snippet, it's part of vector class

void push_back(object &&x) {
        //do something
        objects[size++] = std::move(x);
    }

I know that std::move return a rvalue reference of the object, but the push_back member function already has rvalue reference x as parameter, isn't the std::move here unnecessary?

Another question is if we have a rvalue reference of a class object, we still need to use std::move on its member if we want to call move instead of copy right? like the code below:

A& operator=(A&& other) {
     member = std::move(other.member);
     return *this;
}
like image 332
codesavesworld Avatar asked Nov 08 '19 05:11

codesavesworld


People also ask

Why is std :: move necessary?

std::move itself does "nothing" - it has zero side effects. It just signals to the compiler that the programmer doesn't care what happens to that object any more. i.e. it gives permission to other parts of the software to move from the object, but it doesn't require that it be moved.

Why do we need rvalue reference?

Rvalue references is a small technical extension to the C++ language. Rvalue references allow programmers to avoid logically unnecessary copying and to provide perfect forwarding functions. They are primarily meant to aid in the design of higer performance and more robust libraries.

What is the difference between std :: forward and std :: move?

std::move takes an object and casts it as an rvalue reference, which indicates that resources can be "stolen" from this object. std::forward has a single use-case: to cast a templated function parameter of type forwarding reference ( T&& ) to the value category ( lvalue or rvalue ) the caller used to pass it.

Where is std :: move defined?

In C++11, std::move is a standard library function that casts (using static_cast) its argument into an r-value reference, so that move semantics can be invoked. Thus, we can use std::move to cast an l-value into a type that will prefer being moved over being copied. std::move is defined in the utility header.


2 Answers

isn't the std::move here unnecessary?

No. Types and value categories are different things.

(emphasis mine)

Each C++ expression (an operator with its operands, a literal, a variable name, etc.) is characterized by two independent properties: a type and a value category.

The following expressions are lvalue expressions:

the name of a variable, a function, a template parameter object (since C++20), or a data member, regardless of type, such as std::cin or std::endl. Even if the variable's type is rvalue reference, the expression consisting of its name is an lvalue expression;

std::move converts lvalue to rvalue (xvalue). As a named variable, x is an lvalue, std::move converts it to rvalue in objects[size++] = std::move(x); then the move assignment operator is supposed to be used. Otherwise, copy assignment operator will be used instead; lvalue can't be bound to rvalue reference.

we still need to use std::move on its member if we want to call move instead of copy right?

Yes, same reason as above.

like image 67
songyuanyao Avatar answered Oct 23 '22 13:10

songyuanyao


x has a name, thus it's an lvalue inside the function. The rvalue reference was bound to the lvalue x. std::move casts it back to the rvalue that was passed in.

like image 31
Jesper Juhl Avatar answered Oct 23 '22 13:10

Jesper Juhl