LoginSignup
6
5

More than 5 years have passed since last update.

[C++] RVO(Return Value Optimisation)

Last updated at Posted at 2016-06-11

Recently I read a book talking about the c++11, which described a very interesting thing. The RVO/NRVO of compiler.

What is RVO

The Wikipedia has a very clearly explanation.

In the context of the C++ programming language, the return value optimization (RVO) is a compiler optimization that involves eliminating the temporary object created to hold a function's return value.

Write some code

class A {
public:
    A() {
        cout << "Default constructor!" << endl;
    }
    A(const A& other) {
        cout << "Copy contructor!" << endl;
    }
};

A getA() {
    return A();
}

int main() {
    A b = getA();
    return 0;
}

At last we found that the copy constructor was not called. Only the default constructor was called. That is to say, the compiler just initialized one instance of A in this program. The return value from the function getA() will have same memory address with the variable b.

Default constructor!

One more interesting thing is that we can let the compiler not to do this optimization. When we compile the code with gcc/g++, we can append this flag -fno-elide-constructors to gcc/g++ to turn off RVO.

Then we try to run the code described before with this flag. The copy constructor is called twice.

Default constructor!
Copy contructor!
Copy contructor!

If we turn off this optimization, there is a hidden temporary object, the compiler will first copy the return value to a temporary variable, then copy the temporary variable to the variable which will be assigned from the method return value.

tmp = a; // one copy
b = tmp; // another copy

About NRVO

As @tamy0612 described bellow, my old version code is a NRVO. If we return a named object inside the function. This may be optimized by the NRVO if the compiler supports NRVO. Also we can turn off the NRVO by using the flag -fno-elide-constructors.

A getA() {
    A a;
    printf("Address of a: %p\n", &a);
    return a;
}

int main() {
    A b = getA();
    printf("Address of b: %p\n", &b);
    return 0;
}

With NRVO

Default constructor!
Address of a: 0x7fff583c35a8
Address of b: 0x7fff583c35a8

Turn off NRVO with -fno-elide-constructors

Default constructor!
Address of a: 0x7fff52ebb578
Copy contructor!
Copy contructor!
Address of b: 0x7fff52ebb5a8
6
5
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
5