RVO优化

RVO--Return Value Optimization
概述
返回值优化(Return Value Optimization,简称RVO)是一种编译器优化机制:

当函数需要返回一个对象的时候,如果自己创建一个临时对象用户返回,那么这个临时对象会消耗一个构造函数(Constructor)的调用、一个复制构造函数的调用(Copy Constructor)以及一个析构函数(Destructor)的调用的代价。而如果稍微做一点优化,就可以将成本降低到一个构造函数的代价,这样就省去了一次拷贝构造函数的调用和依次析构函数的调用。

下面我们看个例子

#include <iostream>
using namespace std;

class Rational
{
public:
    Rational(int numerator = 0, int denominator = 1) : n(numerator), d(denominator) {
          cout << "Constructor Called..." << endl;
    }

    ~Rational() {
          cout << "Destructor Called... n:" << n << "d:" << d << endl;
    }

    Rational(const Rational& rhs) {
          this->d = rhs.d;
          this->n = rhs.n;
          cout << "Copy Constructor Called..." << endl;
    }

    int numerator() const { return n; }
    int denominator() const { return d; }
private:
    int n, d;
};

const Rational operator*(const Rational& lhs, const Rational& rhs) {
    cout << "----------- Enter operator* -----------" << endl;
    Rational tmp(lhs.numerator() * rhs.numerator(),
        lhs.denominator() * rhs.denominator());
    cout << "----------- Leave operator* -----------" << endl;
    return tmp;
}

int main(int argc, char **argv)
{
    Rational x(1, 5), y(2, 9);
    Rational z = x * y;
    cout << "calc result: " << z.numerator()
        << "/" << z.denominator() << endl;

    return 0;
}

使用gcc4.8.4运行:

Constructor Called...
Constructor Called...
----------- Enter operator* -----------
Constructor Called...
----------- Leave operator* -----------
calc result: 2/45
Destructor Called... n:2d:45
Destructor Called... n:2d:9
Destructor Called... n:1d:5
tmp对象并没有生成和析构,这是为啥呢,原来gcc4.8.4默认开启了RVO优化,下面我们关闭看一下,使用-fno-elide-constructors
> g++ -fno-elide-constructors main.c 
> ./a.out 
Constructor Called...
Constructor Called...
----------- Enter operator* -----------
Constructor Called...
----------- Leave operator* -----------
Copy Constructor Called...
Destructor Called... n:2d:45
Copy Constructor Called...
Destructor Called... n:2d:45
calc result: 2/45
Destructor Called... n:2d:45
Destructor Called... n:2d:9
Destructor Called... n:1d:5

这个才是我们理解的形式。

 
上一篇:ES6 中Class创建对象与继承实现


下一篇:深度探索C++对象模型