Search code examples
c++c++11rvalue-referencemove-semanticsreturn-value-optimization

Efficiency of construction of stl container based on a function return


I have a factory function which return a stl container:

const std::vector<int> f(...) {
    std::vector<int> retval;
    return retval;
}

I guess it is ok to define a stl instance as follow(no error):

const std::vector<int> stl_instance(f(...));

But is it efficient to do so?

Is the temporary stl object directly assigned to stl_instance?


Solution

  • Returning a const rvalue is an anti-pattern in C++11. First consider returning non-const rvalues:

    std::vector<int> f(int n) 
    { 
        return std::vector<int>(n); 
    }
    
    int main() 
    { 
        std::vector<int> v; 
        v = f(3); 
    } 
    

    In C++98/03, this code will go to the heap at least twice:

    1. To create the vector inside of f (if the RVO applies)
    2. To assign from f's return to v.

    If your compiler does not apply the RVO, you get 3 heap allocations.

    In C++11, you only get 1 heap allocation: to create the vector inside of f. This happens regardless of the RVO. The reason is that all the STL containers have move constructors and move assignment operators that have the signatures

    vector( vector&& other );
    vector& operator=( vector&& other );
    

    The rvalue references && will move the resources from inside your creation function directly to their destination. However, your code has the signature

    const std::vector<int> f(int n) 
    { 
        return std::vector<int>(n); 
    }
    

    will disable the move semantics because a T&& (i.e. the argument of the move constructor and assignment operator) will not bind to a const rvalue parameter (i.e. the return value of your function). This effectively makes your code run as under C++98/03 (i.e. with 2 or 3 heap allocations).