-1

有一个带有构造函数的 Complex 类,它为 RVO 打印一条消息。
我已经在 gtest 中测试了 Complex 的 operator+ 方法。
如果发生 RVO,则打印“Complex!!” 留言3次。
但是有“复杂!!” 消息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;
    }
}
4

2 回答 2

7

RVO 不是防止构造对象的优化 - 它是避免不必要的额外复制或移动的优化。

您的示例是构造三个对象(abc),然后再构造两个(a+b循环中的两次)。这些对象都必须构造,没有办法围绕它进行优化 - 编译器无法分解Complex()内部的临时初始化并将operator+其解压缩到.realimagoperator=

如果您检测了您的复制和移动构造函数,您会看到在您的示例中没有调用它们。但他们本来可以的。在被绑定到 in 中的引用之前,在概念上创建的临时operator+()对象被移动到函数的返回中Complex::operator=()。这是通过RVO 省略的动作,如果您使用-fno-elide-constructors.

于 2016-07-14T14:20:15.427 回答
7

返回值优化是复制省略的一种形式。简单来说,它是一种避免复制对象的优化。它不会避免通过其他方式创建对象。

您可以通过观察复制和移动构造函数的副作用来验证是否已应用 RVO。

您的复制构造函数没有副作用,因此无法观察 RVO 是否已应用。

当 RVO 发生时,两个“复杂!!” 不应打印调用 operator+ 的消息。

不,这些消息打印在类的常规(非复制)构造函数中。RVO 对调用常规构造函数的次数没有影响。

于 2016-07-14T14:17:31.500 回答