【问题标题】:C++: should I explicitly use std::move() in a return statement to force a move? [duplicate]C++:我应该在 return 语句中明确使用 std::move() 来强制移动吗? [复制]
【发布时间】:2018-01-22 16:03:38
【问题描述】:

编辑:它不是重复的,因为这个问题询问编译器在 O0 中的决定。

据说here 名称返回值优化(NRVO)是许多编译器支持的优化。但它是必须的还是只是一个不错的优化?

我的情况是,为了方便调试,我想使用-O0 进行编译(即没有优化),但我也希望为返回对象(例如向量)的返回语句启用 NRVO。如果 NRVO 不是必须的,编译器可能不会在 -O0 模式下执行此操作。在这种情况下,我应该更喜欢这段代码吗:

std::vector<int> foo() {
    std::vector<int> v(100000,1); // an object that is really big..
    return std::move(v);  // explicitly move
}

在下面?

std::vector<int> foo() {
    std::vector<int> v(100000,1);
    return v;    // copy or move?
}

编辑:我使用的编译器是 GCC6,但我希望代码独立于编译器。

【问题讨论】:

  • 返回值是否被复制或移动取决于函数的返回类型及其调用上下文。函数内部发生的任何事情都不会对此产生任何影响。
  • move 是多余的,因为该值已经是一个右值(xvalue),并且它禁止复制省略。所以总体上只是悲观。另外,不要优化未优化的构建。
  • 您唯一关心的应该是最佳算法的正确性和选择。代码优化是编译器的关注点。几乎总是喜欢按值返回而不是按右值引用返回。

标签: c++ nrvo stdmove


【解决方案1】:

你应该更喜欢

std::vector<int> foo() {
    std::vector<int> v(100000,1);
    return v;    // move or NRVO
}

结束

std::vector<int> foo() {
    std::vector<int> v(100000,1);
    return std::move(v);    // move
}

第二个 sn-p 阻止 NRVO,在最坏的情况下两者都会移动构造。

【讨论】:

  • 为什么搬家施工不好?我认为复制构造是不必要的,因此很糟糕。
  • 在第一个 sn-p 中,您有移动构造函数甚至更好的 NRVO(并且在 C++17 NRVO 中保证 :-))。在第二个 sn-p 中,move 调用阻止了 NRVO,因此您只有 move 构造,这还不错,但我们在第一个 sn-p 中使用更短的代码更好或相等。
  • 并非所有招式都是免费的。一些移动需要额外的工作来确保移动的对象处于有效状态。例如,unordered_map 将为移动的对象分配存储桶。
  • @Chad:仅在某些实现中。 libc++ 没有。我怀疑 libstdc++ 没有。 howardhinnant.github.io/container_summary.html
  • (N)RVO 和移动不是一回事。 RVO 在 C++11 之前就存在了——它只是编译器可以采用的一种允许的优化。正确,复制构造函数永远不会被调用 - 此时 v 是一个右值(准确地说是一个 xvalue),所以接受右值的构造函数(移动构造函数)比那个更好的匹配没有(复制构造函数)。
猜你喜欢
  • 1970-01-01
  • 2015-06-04
  • 2021-10-03
  • 2012-06-12
  • 2011-07-28
  • 2019-09-29
  • 1970-01-01
  • 2019-12-31
  • 2018-02-14
相关资源
最近更新 更多