liveBook · Manning

Return value optimization

As explained in 100 C++ Mistakes and How to Avoid Them

Return value optimization is a compiler optimization that constructs a function's returned object directly in the destination storage, eliminating unnecessary temporary objects and copy operations.

Return value optimization (RVO) constructs a function's returned object directly in the caller's destination storage. It removes unnecessary temporary objects, copy-constructor calls, and related destruction overhead. section 9.0 section 9.3

Returning a complex-number result

A conventional operator+ creates a named local sum and returns it, potentially causing several constructions before c3 is initialized. Code the return as `return Complex(lhs.real + rhs.real, lhs.imag + rhs.imag);` instead. This form exposes the result construction directly and is cleaner even when the compiler already performs RVO. section 9.3

Avoid these tempting workarounds:

  • Do not return a pointer to a heap-allocated result merely to reduce construction; allocation makes the syntax awkward and transfers deletion responsibility to the caller. section 9.3
  • Do not return a reference or pointer to a local object; its storage becomes invalid when the function ends, producing undefined behavior. section 11.4
  • Return assignment operators by reference, using `return *this`, rather than returning a copied temporary; this preserves chained assignments without an extra object. section 9.4
Listing 9.7 A typical approach to adding complex numbers
class Complex {
private:
    double real;
    double imag;
public:
    Complex(double r, double i) : real(r), imag(i) {std::cout<<"x\n";}
    Complex(const Complex& o) : real(o.real), imag(o.imag) 
        { std::cout<<"y\n"; }
    friend const Complex operator+(const Complex&, const Complex&);
};
const Complex operator+(const Complex& lhs, const Complex& rhs) {
    Complex sum(lhs.real+rhs.real, lhs.imag+rhs.imag);     #1
    return sum;                                            #2
}
 
int main() {
    Complex c1(-2, 3.3);                                   #3
    Complex c2(3, -1);    q                                #4
    Complex c3 = c1 + c2;                                  #5
}

Trace the five potential constructor calls in complex-number addition, then compare the direct-return form that is coded for RVO. section 9.3

How 100 C++ Mistakes and How to Avoid Them covers it

How deep it goes
Explains constructor-call consequences and safer return forms, but defers compiler implementation details.
Examples
Demonstrates complex-number addition, pointer and reference workarounds, chained assignment, and string concatenation.
What it assumes
Assumes basic C++ classes, constructors, copy constructors, operators, references, pointers, and automatic storage.
What you can do after
Apply it by returning computed values directly, preserving references for assignment operators, and rejecting dangling local references.
How it connects
Connects temporary objects, copy constructors, operator overloading, copy assignment operators, object lifetime, and heap allocation.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of 100 C++ Mistakes and How to Avoid Them. The section links point to the parts of the book it draws on.