繁体   English   中英

使用 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推入向量后就不再需要了。

我的问题是

  • 写有意义吗

     v.push_back(std::move(foo));

    向编译器表明它可以获取 foo 的内容。

  • 如果需要,是否真的需要? 实际上,编译器可能会注意到foo在被推送后立即被破坏,以便可以移动它......实际的编译器是否使用这些类型的优化?

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

A) object 是临时未命名的 object。

B) object 从 function 返回。

还有一些其他要求,但以上两个都不适用于此处。 所以不允许转换为移动/省略。

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

编译器是否可以优化它取决于Obj到底是什么样子,在做“复杂的东西修改foo ”时调用什么函数, Obj是否有移动构造函数,等等。 您应该尝试对代码进行编译和基准测试并亲自查看,或者使用像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
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM