【问题标题】:RVO and NRVO optimisations + C++11 move operatorRVO 和 NRVO 优化 + C++11 移动运算符
【发布时间】:2013-12-19 18:39:51
【问题描述】:

我试图弄清楚 RVO 和 NRVO 如何与新的 C++11 移动运算符一起工作。 我用几个例子起草了一个虚拟类。

编辑:只显示最重要的代码部分。

完整的源代码可用here

我有两个函数将类作为引用并返回值或引用:

VOpt& fChangeClassRetRef(VOpt &m) {
    m.setX(21);
    return m;
}

VOpt fChangeClassRetValue(VOpt &m) {
    m.setX(21);
    return m;
}

当我调用这些函数时,输出如下:

VOpt &m14 = fChangeClassRetRef(m13);

m14 = fChangeClassRetRef(m11);
     -> Copy Assignment Operator

m14 = fChangeClassRetValue(m11);
     -> Copy Constructor
     -> C++11 Move Operator

当使用左值引用时,不会调用复制构造函数。否则,那些函数(接收引用作为参数)仍然调用复制构造函数。

此功能是否依赖于编译器?我做错了吗?

【问题讨论】:

  • 概念是正交的。如果有 RVO 或 NRVO,就没有移动任何东西的余地。
  • 这里有很多代码 - 最好将程序简化到让您感到困惑的情况,并说明这些情况的预期行为。
  • 更有趣的情况是,如果您删除所有引用(按值传递 m,按值返回)。然后 C++03 允许复制省略(尽管没有编译器这样做),但 C++11 不允许。不过它确实使用了移动构造函数。
  • @MarcGlisse:呃,什么? C++11 同样允许复制省略。
  • @MarcGlisse:你到底在说什么? C++11 没有禁止任何在 C++03 中合法的复制省略。事实上,编译器何时可以执行隐式移动的定义是何时可以合法地删除副本。

标签: c++ c++11 move-semantics rvo nrvo


【解决方案1】:
m14 = fChangeClassRetRef(m11);
     -> Copy Assignment Operator

函数返回一个引用(左值),它不能做移动赋值,因为参数不是右值。

m14 = fChangeClassRetValue(m11);
     -> Copy Constructor
     -> C++11 Move Operator

复制构造函数在内部触发以创建返回值。它必须是复制构造函数而不是移动构造函数,因为参数是引用(左值)。将返回值赋值给m14 使用移动赋值运算符,因为参数是右值。

【讨论】:

  • 感谢您的回复...非常有帮助。
【解决方案2】:

你有:

// Change the value of the class, return ref!
VOpt& fChangeClassRetRef(VOpt &m) {
    m.setX(21);
    return m; //#1
}

是这样使用的:

// VOpt m11;
VOpt m12 = fChangeClassRetRef(m11); // #2

让我们分析一下:#1 返回参数的名称(不是局部变量),因此 RVO 和 NRVO 都不适用于此处。现在fChangeClassRetRef 返回对m 绑定的任何位置的引用,在#2 中是m11。因此,我们使用对m11 的左值引用来初始化m12。在这种情况下,他的编译器不能调用移动构造函数,因为它需要一个右值,而且正如我们刚刚看到的,您提供的是一个左值。复制构造函数被调用。

另一种情况类似。你有

VOpt fChangeClassRetValue(VOpt &m) {
    m.setX(21);
    return m;
}

这样称呼的:

// VOpt m13; 
VOpt &m14 = fChangeClassRetRef(m13);

如上所述,这里既没有 RVO,也没有 NRVO,因为您要返回参数的名称。

函数按值返回,而您返回的是左值。 (在某些情况下,允许编译器将返回的左值视为右值,但在这种情况下则不然。)因此无法调用移动构造函数并调用复制构造函数。

【讨论】:

  • 感谢您的回复!我想我明白了。
猜你喜欢
  • 2011-09-25
  • 2018-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多