RVO和NRVO优化+C++11移动操作员
RVO and NRVO optimisations + C++11 move operator
我正试图弄清楚RVO和NRVO如何与新的C++11移动运算符一起工作。我草拟了一个有几个例子的模拟课堂。
编辑:只显示代码中最重要的部分。
这里提供完整的源代码。
我有两个函数,它们将类作为引用并返回值或引用:
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
当使用左值引用时,不会调用复制构造函数。否则,那些函数(接收引用作为参数)仍然调用复制构造函数。
此功能是否依赖于编译器?我做错什么了吗?
m14 = fChangeClassRetRef(m11);
-> Copy Assignment Operator
函数返回一个引用(左值),它不能执行移动赋值,因为参数不是右值。
m14 = fChangeClassRetValue(m11);
-> Copy Constructor
-> C++11 Move Operator
复制构造函数在内部触发以创建返回值。它必须是复制构造函数,而不是移动构造函数,因为参数是引用(左值)。将返回值赋值给m14
使用移动赋值运算符,因为参数是右值。
您有:
// 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
。在这种情况下,编译器不能调用move构造函数,因为它需要一个右值,正如我们刚刚看到的,您提供的是一个左值。复制构造函数被调用。
另一种情况类似。你有
VOpt fChangeClassRetValue(VOpt &m) {
m.setX(21);
return m;
}
这就是所谓的
// VOpt m13;
VOpt &m14 = fChangeClassRetRef(m13);
如上所述,这里既没有RVO也没有NRVO,因为您正在返回参数的名称。
函数按值返回,而您正在返回一个左值。(在某些情况下,编译器可以将返回的左值视为右值,但在这种情况下不允许。)因此,不能调用move构造函数,而是调用copy构造函数。
相关文章:
- 将对象移动到std::shared_ptr
- 何时在引用或唯一指针上使用移动语义
- 如何从具有移动语义的类对象中生成共享指针
- 将shared_ptr移动到<StructA>shared_ptr<变体<结构A、结构 B>>
- C / C++ 移位/偏移/向左或向右移动位图?
- MSVC将仅移动结构参数解释为指针
- 自定义先决条件对移动分配运算符有效吗
- 返回值优化:显式移动还是隐式
- 当有分配器意识的容器被复制/移动时,反弹分配器是否被复制/移走
- 为什么复制而不是移动数据元素?
- <<操作员在下面的行中工作
- 可以使用移动语义更改或改进此C++代码吗?
- 使lambda不可复制/不可移动
- c++在使用指针时移动语义
- 将QGraphicsItem的移动区域限制在多边形区域内
- 分开副本/移动分配操作员
- 位移动操作员无视数据大小
- 操作员移动装载的工作原理
- RVO和NRVO优化+C++11移动操作员
- 异常安全移动操作员