Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding std::vector::push_back(std::move(v[i])) [duplicate]

Tags:

c++

Beginner question.

In the following code, I was expecting v2[0]=1 would also change the value of v1, but it seems not.

push_back seems to receive T&& since C++11(ref), and std::move is equivalent to static_cast<T&&>(t); according to this answer. Also std::vector::operator[] returns reference(ref). So I thought v2.push_back(std::move(v1[0])); would make a reference to the same value.

What am I missing here? I thought the output would be 1 and 1.

#include <iostream>
#include <vector>

int main(){
    std::vector<int> v1{5}, v2;
    v2.push_back(std::move(v1[0])); 

    v2[0] = 1;

    std::cout << v1[0] << '\n';
    std::cout << v2[0] << '\n';

    // output:
    // 5
    // 1
}
like image 457
starriet Avatar asked Sep 12 '25 03:09

starriet


2 Answers

So I thought v2.push_back(std::move(v1[0])); would make a reference to the same value.

v1[0] is an lvalue referring to the first element of the vector, and std::move(v1[0]) is an rvalue referring to that element. The move has little to do with the behaviour of the example.

But the elements of v2 aren't references. They are integers. So, you initialise the non-reference second element of the vector using the value of the first element through the reference. It's analogous to following simpler example:

int a = 5;
int& ref = a;
int b = ref;  // b is not a reference
b = 1;        // this has no effect on a,
              // because it is a separate object from b

std::cout << a << '\n';
std::cout << b << '\n';
like image 191
eerorika Avatar answered Sep 13 '25 16:09

eerorika


A vector like all containers can't store references. If you want v2 elements reference some elements of v1, you can use std::reference_wrapper<>.

#include <iostream>
#include <vector>
#include <functional>  // for std::reference_wrapper<>

int main() {
   std::vector<int>  v1{ 5 };
   std::vector<std::reference_wrapper<int>>  v2;
   v2.push_back( v1[0] );  // move has no sense, so illegal here

   // v2[0] = 1;   illegal a reference_wrapper is not exactly a reference
   // we must use : v2[0].get() = 1;
   // or            static_cast<int&>(v2[0]) = 1;
   v1[0] = 3;    // possible

   std::cout << v1[0] << ' ' << v2[0] << '\n';

   // output: 3 3
}

Note that referencing elements in vector v1 is not a good idea, because any modification in v1 will made all references invalid.

like image 36
dalfaB Avatar answered Sep 13 '25 17:09

dalfaB