有一个带有构造函数的Complex类,它为RVO打印一条消息
我在gtest中测试过Complex的运算符+方法
如果发生了RVO,请打印"复杂!!"消息3次。
但是有#34;复杂!!"消息5次
我认为没有发生RVO
我已经用c ++ 98和c ++ 11编译了这段代码
为什么不发生RVO?
#include <stdio.h>
class Complex {
friend Complex operator+(const Complex&, const Complex&);
public:
Complex(double r = 0.0, double i = 0.0) : real(r), imag(i) { printf("\nComplex!!\n");}
Complex(const Complex& c) : real(c.real), imag(c.imag) {}
Complex& operator=(const Complex& c) {
real = c.real;
imag = c.imag;
return *this;
}
~Complex() {}
private:
double real;
double imag;
};
Complex operator+(const Complex& lhs, const Complex& rhs)
{
return Complex(lhs.real + rhs.real, lhs.imag + rhs.imag);
}
int main()
{
Complex a(1.0), b(2.0), c;
for (int i = 0; i < 2; i++) {
c = a + b;
}
}
答案 0 :(得分:7)
返回值优化是复制省略的一种形式。简单来说,它是一种避免复制对象的优化。它不会通过其他方式避免创建对象。
您可以通过观察副本和移动构造函数的副作用来验证是否已应用RVO。
您的复制构造函数没有副作用,因此无法观察RVO是否已应用。
当发生RVO时,两个&#34;复杂!!&#34;不应打印调用operator +的消息。
没有。这些消息打印在类的常规(非复制)构造函数中。 RVO对常规构造函数的调用次数没有影响。
答案 1 :(得分:7)
RVO不是防止对象构造的优化 - 它是一种优化,可以避免不必要的额外复制或移动。
您的示例是构建三个对象(a
,b
和c
),然后在循环中构建两个(a+b
两次)。所有必须构造的对象,没有办法优化 - 编译器不能拆分Complex()
中的operator+
临时初始化并将其解压缩到赋值中real
内的imag
和operator=
。
如果您已经为自己的副本和移动构造函数进行了检测,那么您会看到它们未在您的示例中调用。但他们本来可以。在operator+()
中创建的临时值在被绑定到Complex::operator=()
中的引用之前在概念上被移动到函数的返回中。