1
votes

Add element at the end Adds a new element at the end of the vector, after its current last element. The content of val is copied (or moved) to the new element.

Hi, the above is from http://www.cplusplus.com/reference/vector/vector/push_back/

I am a little bit confused by the word "move".I understand the rvalue reference and lvalue reference.

for example,

vector<int> source = {1,2,3};
vector<int> copy;
copy.push_back(source[0]);
cout<<source[0];   // why it doesn't throw error since source[0] is moved to copy ?

because source[0] is rvalue, so push_back actually moves source[0] rather than copy it. Then after this operator, access to source[0] is still valid? why?

2
".I understand the rvalue reference and lvalue reference" what is source[0]? what is std::move(source[0])?UKMonkey
source[0] is not an rvalue. It is an lvalue. Even if it was, you are assuming that accessing a moved-from object "throws an error". The C++ standard doesn't require that, in any shape, matter, or form. It might throw an error, for some arbitrary class, but it may not. The C++ standard does not require either one or the other.Sam Varshavchik
Could this be a duplicate of stackoverflow.com/q/2275076/7363404? I'm not too sure..Axiumin_
Thank you for replying. I thought source[0] was syntax-sugar of function call, just like calling addInt(2,3) for int addInt(int i,inj); . But someone told me below that the return value type is reference, then source[0] is lvalue type, which makes sense to me. Otherwise, it will be rvalue type.Lin Paul
"why it doesn't throw error since source[0] is moved to copy" - In many cases you shouldn't assume something wrong in C++ will always throw an error. If you have undefined behavior, your program could crash, appear to work, or do anything else.eesiraed

2 Answers

4
votes
copy.push_back(source[0]);

This passes a const lvalue reference to the function. As such, std::vector is not allowed to touch it; and is forced to copy. This will keep source[0] valid.

copy.push_back(std::move(source[0]));

Will pass an rvalue to the function. This can then be passed into the constructor of the object, and moved.

To follow up though; attempting to use an object that has been moved will usually not error for std objects; because it should leave the object in an "empty" state. You're also using int, which isn't an object, and as such can't really be moved.

0
votes

because source[0] is rvalue

No, the expression source[0] is lvalue, since the index operator [] of a vector returns a lvalue reference of the element type. See this link.

why it doesn't throw error since source[0] is moved to copy ?

No, the behavior of a moved object is user defined. You can make it throw an error, or you can make operations fail silently, etc. For a scalar (in your case int), move constructing usually leaves the original object untouched.