简体   繁体   English

std :: move在vector :: insert和push_back上的行为不同

[英]std::move behaves differently on vector::insert and push_back

I noticed a difference in behavior between vector::push_back and insert . 我注意到vector::push_backinsert之间的行为有所不同。

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. 向量中的第6个元素将添加到底部,并从上一个位置删除。

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. 第6个元素将插入到第一个位置,但不会从前一个位置删除。

Why std::move does not work in insert() as in push_back() ? 为什么std::move无法像push_back()那样在insert()工作?

17.6.4.9 Function arguments [res.on.arguments]/p1/b3 says: 17.6.4.9函数自变量[res.on.arguments] / p1 / b3说:

1 Each of the following applies to all arguments to functions defined in the C++ standard library, unless explicitly stated otherwise. 1下列各项均适用于C ++标准库中定义的函数的所有参数,除非另有明确说明。

... ...

  • 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. [ 注意 :如果参数是T&&形式的泛型参数,并且绑定了类型A的左值,则该参数将绑定到左值引用(14.8.2.1),因此上一句话不涉及该参数。 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. end note ] [ 注意 :如果程序在将左值传递给库函数的同时将左值转换为xvalue(例如,通过使用参数move(x)调用该函数),则程序将有效地要求该函数处理该左值作为临时的。 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. 简而言之,vector假设在insertpush_back&&引用的参数都是临时的,因此不进行预防性别名检查。

As it turns out, assuming you inserted or push_back'd an lvalue, the push_back algorithm never needs to check for aliasing anyway. 事实证明,假设您插入或推入左值, push_back算法再也不需要检查别名。 However the insert algorithm does (I'm specifically speaking of vector , and not other containers). 但是insert算法确实可以(我是专门针对vector ,而不是其他容器)。 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. 因此,当您使用move ,您不会注意到push_back上没有别名检查,因为它们无论如何都不会有所作为。 However you do notice the lack of them on insert . 但是,您确实会注意到insert缺少它们。

Iterators are only valid as long as the collection class, in this case vector isn't modified. 迭代器仅在collection类的情况下才有效,在这种情况下, vector不会被修改。 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! 因此,无论哪种情况, iter将无效,并且会发生坏事! 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. 相反,请考虑将要添加的元素复制到新容器中,然后添加它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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