使用std::move的矢量构建优化



我正在构建一些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
}

最新更新