简体   繁体   中英

std::move behaves differently on vector::insert and push_back

I noticed a difference in behavior between vector::push_back and insert .

When I do

iter = myVector.begin() + 5;
myVector.push_back(std::move(*iter));

The 6th element in the vector is added to the bottom and gets deleted from the previous position.

Whereas, if I do this:

iterBegin = myVector.begin();
myVector.insert(iterBegin,std::move(*(iterBegin + 5)));

The 6th element gets inserted in the first position, but it does not get deleted form the previous position.

Why std::move does not work in insert() as in push_back() ?

17.6.4.9 Function arguments [res.on.arguments]/p1/b3 says:

1 Each of the following applies to all arguments to functions defined in the C++ standard library, unless explicitly stated otherwise.

...

  • If a function argument binds to an rvalue reference parameter, the implementation may assume that this parameter is a unique reference to this argument. [ Note : If the parameter is a generic parameter of the form T&& and an lvalue of type A is bound, the argument binds to an lvalue reference (14.8.2.1) and thus is not covered by the previous sentence. end note ] [ Note : If a program casts an lvalue to an xvalue while passing that lvalue to a library function (eg by calling the function with the argument move(x) ), the program is eectively asking that function to treat that lvalue as a temporary. The implementation is free to optimize away aliasing checks which might be needed if the argument was an lvalue. endnote ]

In short, vector assumes the argument referenced by && in both insert and push_back is a temporary and thus does no preventative aliasing checks.

As it turns out, assuming you inserted or push_back'd an lvalue, the push_back algorithm never needs to check for aliasing anyway. However the insert algorithm does (I'm specifically speaking of vector , and not other containers). So when you use move , you don't notice the lack of aliasing checks on push_back , because they would not make a difference anyway. However you do notice the lack of them on insert .

Iterators are only valid as long as the collection class, in this case vector isn't modified. Once you insert the first time, you invalidate your iterators and the result is undefined.

So in either case, iter becomes invalid and bad stuff will happen! Or worse, it seems to work except on release builds, or on that one old machine, or when the moon is full, etc.

Instead, consider copying the elements you want to add to a new container, and then add them.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM