Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing vector with std::move function signature

Consider the code below

void foo(std::vector<int> v)
{
   //do something here
}
//calling the function
vector<int> v1 = {1,2,3};
foo(std::move(v1));

My question is, isn't the function foo supposed to have signature void foo(std::vector<int>&& v) for it to be able to take the r value reference of the vector?

like image 739
Kraken Avatar asked Jan 20 '20 20:01

Kraken


People also ask

How do you pass a vector to another function?

When we pass an array to a function, a pointer is actually passed. However, to pass a vector there are two ways to do so: Pass By value. Pass By Reference.

How do you pass a part of a vector in C++?

Slicing a Vector in C++ Method 1: The idea is to copy the elements from this range X to Y to a new vector and return it. Copy the elements in these range between these iterators using copy() function in vector.

Should I pass vector by reference or value?

vector<int> is non-array, non-reference, and non-pointer - it is being passed by value, and hence it will call copy-constructor. So, you must use vector<int>& (preferably with const , if function isn't modifying it) to pass it as a reference.

Does STD move invalidate pointers?

No. An object still exists after being moved from, so any pointers to that object are still valid.


2 Answers

My question is, isnt the function foo supposed to have signature void foo(std::vector<int>&& v) for it to be able to take the r value reference of the vector?

If that's what you want, then yes, but that doesn't mean what you have is incorrect. When you pass something to a function it copy initializes the parameter from the source. That means if you do

vector<int> v1 = {1,2,3};
foo(v1);

then foo gets a copy of v1. With

vector<int> v1 = {1,2,3};
foo(std::move(v1));

We copy initialize v from std::move(v1) and since std::move(v1) is an rvalue reference, the move constructor is chosen for v and v1 gets moved into the function.

So, by taking by value you give the option to the caller to give it a temporary, give it a rvalue reference, which will both move the object into the function, or just let a copy happen. If you had void foo(std::vector<int>&& v) Then you could only pass a temporary or std::move() an lvalue. There would be no way to allow the caller to have a copy made without them making one themselves and then moving that copy into the function.

like image 140
NathanOliver Avatar answered Nov 15 '22 11:11

NathanOliver


isn't the function foo supposed to have signature void foo(std::vector<int>&& v) for it to be able to take the r value reference of the vector?

It is std::vector<int>'s move constructor the one with such a signature.

The function foo() takes as argument an std::vector<int> object by value:

void foo(std::vector<int> v) {
   // ...
}

The parameter object v has to be constructed somehow. The argument passed to foo() is used to construct this parameter object.

By calling foo() as in the expression foo(std::move(v1)), the parameter object in foo(), v, is move constructed. This is in contrast with calling foo() as in the expression foo(v1), which results in the parameter object v being copy constructed.

It is therefore the parameter object's move constructor (i.e., v, an std::vector<int> object) the one taking std::vector<int>&&.

like image 20
ネロク・ゴ Avatar answered Nov 15 '22 12:11

ネロク・ゴ