我正在构建一些std::vector<Obj>
,其中Obj
是可以移动、构造和分配的大对象(例如Obj
是大向量(。代码通常是一个循环,如
std::vector<Obj> v;
while (...) {
Obj foo = some client code(...);
// ... some complicated stuff modifying foo
v.push_back(foo);
}
正如您所看到的,foo
在向量中被推入后就不需要了。
我的问题是
写有意义吗
v.push_back(std::move(foo));
以向编译器指示它可以接受foo的内容。
如果真的需要,那它真的需要吗?事实上,编译器可能会注意到
foo
在被推送之后就被销毁了,这样它就可以被移动。。。实际的编译器是否使用这些类型的优化?
除非在非常特殊的情况下,否则编译器不允许在没有显式移动的情况下调用move构造函数或删除对象(即,强制转换为右值引用;可能通过std move(。
A( 该对象是一个临时的未命名对象。
B( 对象正从函数返回。
还有一些其他要求,但以上两项都不适用于此。因此,不允许转换为移动/省略。
编译器有时可以使用"好像"规则将副本转换为移动,然后销毁,但这非常困难,而且往往很脆弱,所以你永远不应该依赖它
编译器是否能对其进行优化取决于Obj
的外观,以及在执行"复杂物质修饰CCD_ 7";,Obj
是否有move构造函数,等等。你应该尝试编译和基准测试代码,自己看看,或者使用类似的在线服务https://godbolt.org/查看生成了什么汇编代码。
然而,最好的方法是避免完全复制或移动。您可以通过调用emplace_back()
来直接在向量中构造Obj
,然后在适当的位置对其进行修改,如下所示:
while (...) {
v.emplace_back();
Obj &foo = v.back();
// ... some complicated stuff modifying foo
}
你可以用C++17:把它写得稍微短一点
while (...) {
Obj &foo = v.emplace_back();
// ... some complicated stuff modifying foo
}