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

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

本文关键字:back push move vector insert std      更新时间:2023-10-16

我注意到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()中那样工作?

17.6.4.9函数参数/res.on.arguments]/p1/b3表示:

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

  • 如果函数参数绑定到右值引用参数,则实现可能会假设此参数是对的唯一引用这个论点。注意:如果参数是形式为T&&且类型为A的左值绑定,则参数绑定左值参考(14.8.1.1),因此不在上一句。——结束注释][注释:如果程序强制转换将左值传递到xvalue,同时将该左值传递给库函数(例如,通过调用参数为move(x)的函数)程序正在请求该函数将该左值视为短暂的该实现可以免费优化消除混叠检查如果参数是左值,则可能需要它尾注]

简而言之,vector假定insertpush_back&&引用的自变量是临时的,因此不进行预防性混叠检查。

事实证明,假设您插入或推回了一个左值,push_back算法无论如何都不需要检查混叠。然而,insert算法确实如此(我具体指的是vector,而不是其他容器)。因此,当您使用move时,您不会注意到push_back上缺少混叠检查,因为它们无论如何都不会有什么不同。然而,您确实注意到insert上缺少它们。

迭代程序只有在集合类有效的情况下才有效,在这种情况下vector没有被修改。一旦第一次插入,就会使迭代器无效,结果是未定义的。

因此,在任何一种情况下,iter都会失效,并且会发生不好的事情!或者更糟的是,它似乎可以工作,除了发布版本,或者在那台旧机器上,或者当月亮满月时,等等。

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