使用 std::move 优化向量构建

Vector building optimization using 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 被推入向量后就不再需要了。

我的问题是

编译器能不能优化它取决于Obj到底是什么样子,你在做“复杂的东西修改foo时调用了什么函数,Obj是否有一个移动构造函数,等等。您应该尝试对代码进行编译和基准测试并亲自查看,或者使用像 https://godbolt.org/ 这样的在线服务来查看生成的汇编代码。

但是,最好的方法是完全避免复制或移动。您可以通过调用 emplace_back() 直接在 vector 中构造一个 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
}

除非在非常特殊的情况下,否则不允许编译器调用移动构造函数或在您未明确移动(即转换为右值引用;可能通过标准移动)的情况下省略对象。

A) 该对象是一个临时的未命名对象。

B) 对象正在从函数返回。

还有一些其他要求,但以上两个都不适用。所以不允许转换为 move/elision。

编译器有时可以使用 as-if 规则将副本转为移动,然后销毁,但这非常困难且通常很脆弱,因此您永远不要依赖它。