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

时间:2013-07-26 05:26:51

标签: c++ c++11 std stdvector

我注意到vector::push_backinsert之间的行为存在差异。

当我这样做时

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

向量中的第6个元素添加到底部,并从之前的位置删除。

然而,如果我这样做:

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

第6个元素插入第一个位置,但不会从前一个位置删除。

为什么std::moveinsert()中的push_back()不起作用?

2 个答案:

答案 0 :(得分:3)

17.6.4.9函数参数[res.on.arguments] / p1 / b3说:

  

1以下各项适用于定义的函数的所有参数   除非另有明确说明,否则在C ++标准库中。

     

...

     
      
  • 如果函数参数绑定到右值引用参数,则实现可以假定此参数是对其的唯一引用   这个论点。 [注意:如果参数是通用参数   形式T&&和类型A的左值绑定,参数绑定   到左值参考(14.8.2.1),因此不包括在内   上一句。 - 结束记录] [注意:如果程序强制转换   在将左值传递给库函数时左值到xvalue   (例如,通过使用参数move(x)调用函数),   程序正在有效地要求将该左值作为一个函数来处理   临时。该实现可以自由地优化别名检查   如果参数是左值,则可能需要它。 - endnote ]
  •   

简而言之,vector假定&&insertpush_back引用的参数是临时的,因此不进行预防性别名检查。

事实证明,假设您插入或推回了左值,push_back算法无论如何都不需要检查别名。但是insert算法确实如此(我具体说的是vector,而不是其他容器)。因此,当您使用move时,您没有注意到push_back上缺少别名检查,因为它们无论如何都不会产生任何影响。但是你确实注意到insert上没有它们。

答案 1 :(得分:1)

只要集合类(在这种情况下vector未被修改),迭代器才有效。第一次插入后,迭代器无效,结果未定义。

所以在任何一种情况下,iter都会变得无效,会发生不好的事情!或者更糟糕的是,除了在发布版本上,或者在那台旧机器上,或者月亮已满时,它似乎都可以工作。

相反,请考虑将要添加的元素复制到新容器中,然后添加它们。