C ++ Compiler Optimization: Copy elision (Omitted unnecessary copies)

Source: Internet
Author: User

To avoid unnecessary copying of temporary objects, the C ++ compiler usually uses an optimization technique called copy ellision (copy removal), which includes at least two items:

  1. The return value optimization (RVO) prevents copy operations by transferring the allocation location of the space occupied by the return value from the called end to the calling end.
    Optimization of return values includes Optimization of the name return value (nrvo) and the unknown return value (urvo). The difference between the two is that the return value is a named local variable or an unknown temporary object.
  2. Right-value copy optimization: When a temporary object of a class type is copied and assigned to another object of the same type, the copy operation is avoided by directly using this temporary object method.
    This optimization can only be used for the right value (temporary object), but not for the left value.
To test whether the compiler has applied the copy ellision optimization technology, use the following code (from cppnext ).
#include <iostream>struct X{    X() : id(instances++)    {        std::cout << "X" << id << ": construct\n";    }        X(X const& rhs) : id(instances++)    {        std::cout << "X" << id << ": <- " << "X" << rhs.id << ": **copy**\n";        ++copies;    }    // This particular test doesn't exercise assignment, but for    // completeness:    X& operator=(X const& rhs)    {        std::cout << "X" << id << ": <- " << "X" << rhs.id << ": assign\n";    }        ~X() { std::cout << "X" << id << ": destroy\n"; }    unsigned id;        static unsigned copies;    static unsigned instances;};unsigned X::copies = 0;unsigned X::instances = 0;#define CHECK_COPIES( stmt, min, max, comment )                         \{                                                                       \    unsigned const old_copies = X::copies;                              \                                                                        \    std::cout << "\n" comment "\n" #stmt "\n===========\n";             \    {                                                                   \        stmt;                                                           \    }                                                                   \    unsigned const n = X::copies - old_copies;                          \    if (n > max)                                                        \        std::cout << "*** max is too low or compiler is buggy ***\n";   \    if (n < min)                                                        \        std::cout << "*** min is too high or compiler is buggy ***\n";  \                                                                        \    std::cout << "-----------\n"                                        \              << n << "/" << max                                        \              << " possible copies made\n"                              \              << max - n << "/" << max - min                            \              << " possible elisions performed\n\n";                    \                                                                        \    if (n > min)                                                        \        std::cout << "*** " << n - min                                  \                  << " possible elisions missed! ***\n";                \}struct trace{    trace(char const* name)        : name(name)    {        std::cout << "->: " << name << "\n";    }        ~trace()    {        std::cout << "<-: " << name << "\n";    }        char const* name;};void sink(X a){  trace t("sink");}X nrvo_source(){    trace t("nrvo_source");    X a;    return a;}X urvo_source(){    trace t("urvo_source");    return X();}X identity(X a){    trace t("identity");    return a;}X lvalue_;X& lvalue(){    return lvalue_;}typedef X rvalue;int main(){    // Double parens prevent "most vexing parse"    CHECK_COPIES( X a(( lvalue() )), 1, 1, "Direct initialization from lvalue");    CHECK_COPIES( X a(( rvalue() )), 0, 1, "Direct initialization from rvalue");        CHECK_COPIES( X a = lvalue(), 1, 1, "Copy initialization from lvalue" );    CHECK_COPIES( X a = rvalue(), 0, 1, "Copy initialization from rvalue" );    CHECK_COPIES( sink( lvalue() ), 1, 1, "Pass lvalue by value" );    CHECK_COPIES( sink( rvalue() ), 0, 1, "Pass rvalue by value" );    CHECK_COPIES( nrvo_source(), 0, 1, "Named return value optimization (NRVO)" );    CHECK_COPIES( urvo_source(), 0, 1, "Unnamed return value optimization (URVO)" );    // Just to prove these things compose properly    CHECK_COPIES( X a(urvo_source()), 0, 2, "Return value used as ctor arg" );        // Expect to miss one possible elision here    CHECK_COPIES( identity( rvalue() ), 0, 2, "Return rvalue passed by value" );}
Code Description
  1. The lvalue () function returns a reference to the global variable lvalue _ Of the struct X type. Therefore, the lvalue () function returns the left value, which can be used to test the copy optimization of the right value.
  2. The rvalue () function returns the temporary object constructed by the struct X-Type constructor. Therefore, the rvalue () function returns the right value and can be used to test the optimization of right-value copy.
  3. The nrvo_source () function returns the local variable A of the struct X type. Therefore, the nrvo_source () function can be used to test the optimization of the returned value.
  4. The urvo_source () function returns the temporary object constructed by the struct x constructor. Therefore, the urvo_source () function can be used to test the optimization of the unknown return value.
  5. Row 109,110 uses the left and right values to test the right-value copy optimization during direct initialization of class objects.
  6. Row 112,113 uses the left and right values to test the optimization of the right value copy during class Object copy initialization.
  7. Row 115,116 uses left and right values to test the right value copy optimization in the real parameters of common functions.
  8. Row 118,119 is used to test the optimization of the returned values of the specified name and the optimization of the returned values of the Unknown name respectively.

On Windows, gcc4.6.1 is used to compile and run the program as follows:

X0: constructDirect initialization from lvalueX a(( lvalue() ))===========X1: <- X0: **copy**X1: destroy-----------1/1 possible copies made0/0 possible elisions performedDirect initialization from rvalueX a(( rvalue() ))===========X2: constructX2: destroy-----------0/1 possible copies made1/1 possible elisions performedCopy initialization from lvalueX a = lvalue()===========X3: <- X0: **copy**X3: destroy-----------1/1 possible copies made0/0 possible elisions performedCopy initialization from rvalueX a = rvalue()===========X4: constructX4: destroy-----------0/1 possible copies made1/1 possible elisions performedPass lvalue by valuesink( lvalue() )===========X5: <- X0: **copy**->: sink<-: sinkX5: destroy-----------1/1 possible copies made0/0 possible elisions performedPass rvalue by valuesink( rvalue() )===========X6: construct->: sink<-: sinkX6: destroy-----------0/1 possible copies made1/1 possible elisions performedNamed return value optimization (NRVO)nrvo_source()===========->: nrvo_sourceX7: construct<-: nrvo_sourceX7: destroy-----------0/1 possible copies made1/1 possible elisions performedUnnamed return value optimization (URVO)urvo_source()===========->: urvo_sourceX8: construct<-: urvo_sourceX8: destroy-----------0/1 possible copies made1/1 possible elisions performedReturn value used as ctor argX a(urvo_source())===========->: urvo_sourceX9: construct<-: urvo_sourceX9: destroy-----------0/2 possible copies made2/2 possible elisions performedReturn rvalue passed by valueidentity( rvalue() )===========X10: construct->: identityX11: <- X10: **copy**<-: identityX11: destroyX10: destroy-----------1/2 possible copies made1/2 possible elisions performed*** 1 possible elisions missed! ***X0: destroy

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.