为什么不在此代码中应用 RVO
Why does not apply RVO in this code
有一个带有构造函数的 Complex class,它为 RVO 打印一条消息。
我已经在 gtest 中测试了 Complex 的 operator+ 方法。
如果发生 RVO,打印 "Complex!!" 消息 3 次。
但是有"Complex!!"条留言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;
}
}
Return 值优化是 copy 省略的一种形式。简单来说,它是一种避免复制对象的优化。它不会避免通过其他方式创建对象。
您可以通过观察复制和移动构造函数的副作用来验证是否应用了RVO。
你的拷贝构造函数没有副作用,所以无法观察是否应用了RVO。
When RVO is occurred, two "Complex!!" messages in invocation of operator+ should not be printed.
没有。这些消息打印在 class 的常规(非复制)构造函数中。 RVO 对调用常规构造函数的次数没有影响。
RVO 不是防止对象被构造 的优化——它是避免不必要的额外复制或移动的优化。
您的示例正在构建三个对象(a
、b
和 c
),然后再构建两个对象(a+b
在循环中两次)。这些对象都 必须 构造,没有办法围绕它进行优化 - 编译器无法分解 operator+
中的 Complex()
临时初始化并将其解压缩到real
和 imag
在 operator=
.
中的赋值
如果您检测了您的复制和移动构造函数,您会发现在您的示例中没有调用它们。但他们本可以。在 operator+()
中创建的临时对象在概念上被移动到函数的 return 中,然后再绑定到 Complex::operator=()
中的引用。这是 那个 移动通过 RVO 省略了,如果你用 -fno-elide-constructors
.
编译你会看到这个移动
有一个带有构造函数的 Complex class,它为 RVO 打印一条消息。
我已经在 gtest 中测试了 Complex 的 operator+ 方法。
如果发生 RVO,打印 "Complex!!" 消息 3 次。
但是有"Complex!!"条留言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;
}
}
Return 值优化是 copy 省略的一种形式。简单来说,它是一种避免复制对象的优化。它不会避免通过其他方式创建对象。
您可以通过观察复制和移动构造函数的副作用来验证是否应用了RVO。
你的拷贝构造函数没有副作用,所以无法观察是否应用了RVO。
When RVO is occurred, two "Complex!!" messages in invocation of operator+ should not be printed.
没有。这些消息打印在 class 的常规(非复制)构造函数中。 RVO 对调用常规构造函数的次数没有影响。
RVO 不是防止对象被构造 的优化——它是避免不必要的额外复制或移动的优化。
您的示例正在构建三个对象(a
、b
和 c
),然后再构建两个对象(a+b
在循环中两次)。这些对象都 必须 构造,没有办法围绕它进行优化 - 编译器无法分解 operator+
中的 Complex()
临时初始化并将其解压缩到real
和 imag
在 operator=
.
如果您检测了您的复制和移动构造函数,您会发现在您的示例中没有调用它们。但他们本可以。在 operator+()
中创建的临时对象在概念上被移动到函数的 return 中,然后再绑定到 Complex::operator=()
中的引用。这是 那个 移动通过 RVO 省略了,如果你用 -fno-elide-constructors
.