Quantcast
Channel: Active questions tagged gcc - Stack Overflow
Viewing all articles
Browse latest Browse all 22037

How to ensure that RVO (return value optimization) is applied [duplicate]

$
0
0

I am trying to find the best way (i.e. more efficient and preferably more readable) of returning values from a function that has multiple return statements.

While playing a bit with different approaches I discovered three solutions:

  1. test_func1: creates a single lvalue in its scope, modifies it inside the branches and then returns it.
  2. test_func2: creates an rvalue in the return statement of each branch and then returns it.
  3. test_func3: creates an lvalue inside each branch and then returns it.

Here is the code (Compiler Explorerlink):

#include <iostream>#include <vector>struct MyStruct{    int m_value;    std::vector<int> m_vec;    MyStruct( const int value = 10 )    : m_value( value ), m_vec( { 1, 2, 3 } )    {        std::cout << "ctor\n";    }    MyStruct( const MyStruct& rhs )    : m_value( rhs.m_value ), m_vec( rhs.m_vec )    {        std::cout << "copy ctor\n";    }    ~MyStruct( )    {        std::cout << "dtor\n";    }};// can be 1, 2 or 3// 1: generates the fewest lines of assembly// 2: ~45% more lines of assembly compared to 1// 3: ~240% more lines of assembly compared to 1#define FUNC_NUMBER 1#if FUNC_NUMBER == 1// create a single lvalue in the scope, modify it// inside the branches and then return itMyStruct test_func1( const int param ){    std::cout << param << ", Testing...\n";    MyStruct result;    if ( param == 1 )    {        result.m_value = 11;        return result;    }    if ( param == 2 )    {        result.m_value = 22;        return result;    }    result.m_value = 33;    return result;}#elif FUNC_NUMBER == 2// create an rvalue in the return statement of// each branch and then return itMyStruct test_func2( const int param ){    std::cout << param << ", Testing...\n";    if ( param == 1 )    {        return MyStruct( 11 );    }    if ( param == 2 )    {        return MyStruct( 22 );    }    return MyStruct( 33 );}#else// create an lvalue inside each branch and// then return itMyStruct test_func3( const int param ){    std::cout << param << ", Testing...\n";    if ( param == 1 )    {        MyStruct result( 11 );        return result;    }    if ( param == 2 )    {        MyStruct result( 22 );        return result;    }    MyStruct result( 33 );    return result;}#endifint main( ){    using std::cout;#if FUNC_NUMBER == 1    cout << test_func1( 3 ).m_value << '\n';#elif FUNC_NUMBER == 2    cout << test_func2( 3 ).m_value << '\n';#else    cout << test_func3( 3 ).m_value << '\n';#endif}

Apparently, test_func1 and test_func2 have RVO applied (the constructor and the destructor are called only once). However this is not the case for test_func3 (in which the copy constructor is called too).

Why isn't the compiler able to generate smaller code for test_func2 and why does it generate a significant amount of more code for test_func3? Is there any chance that GCC will become smarter in the future releases and generate the same code for all the three cases above?

Also, read the comments on lines 29-32.

===========================================================================================

Now the question is what is the most efficient way (copy-elision and move-elision) of returning values in such cases?


Viewing all articles
Browse latest Browse all 22037

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>