我注意到vector::push_back
和insert
之间的行为存在差异。
当我这样做时
iter = myVector.begin() + 5;
myVector.push_back(std::move(*iter));
向量中的第6个元素添加到底部,并从之前的位置删除。
然而,如果我这样做:
iterBegin = myVector.begin();
myVector.insert(iterBegin,std::move(*(iterBegin + 5)));
第6个元素插入第一个位置,但不会从前一个位置删除。
为什么std::move
与insert()
中的push_back()
不起作用?
答案 0 :(得分:3)
17.6.4.9函数参数[res.on.arguments] / p1 / b3说:
1以下各项适用于定义的函数的所有参数 除非另有明确说明,否则在C ++标准库中。
...
- 如果函数参数绑定到右值引用参数,则实现可以假定此参数是对其的唯一引用 这个论点。 [注意:如果参数是通用参数 形式
T&&
和类型A
的左值绑定,参数绑定 到左值参考(14.8.2.1),因此不包括在内 上一句。 - 结束记录] [注意:如果程序强制转换 在将左值传递给库函数时左值到xvalue (例如,通过使用参数move(x)
调用函数), 程序正在有效地要求将该左值作为一个函数来处理 临时。该实现可以自由地优化别名检查 如果参数是左值,则可能需要它。 - endnote ]
简而言之,vector假定&&
和insert
中push_back
引用的参数是临时的,因此不进行预防性别名检查。
事实证明,假设您插入或推回了左值,push_back
算法无论如何都不需要检查别名。但是insert
算法确实如此(我具体说的是vector
,而不是其他容器)。因此,当您使用move
时,您没有注意到push_back
上缺少别名检查,因为它们无论如何都不会产生任何影响。但是你确实注意到insert
上没有它们。
答案 1 :(得分:1)
只要集合类(在这种情况下vector
未被修改),迭代器才有效。第一次插入后,迭代器无效,结果未定义。
所以在任何一种情况下,iter
都会变得无效,会发生不好的事情!或者更糟糕的是,除了在发布版本上,或者在那台旧机器上,或者月亮已满时,它似乎都可以工作。
相反,请考虑将要添加的元素复制到新容器中,然后添加它们。