Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding eliding rules with regard to c++11

Tags:

c++

c++11

I have been testing with rvalue references and move semantics and want to make sure I understand when a copy should be elided and when it should follow move semantics.

Given the following

class NRVCA
{
public:
    NRVCA(int x):
    {}
    NRVCA(const NRVCA & Rhs)
    {}    
    NRVCA& operator=(const NRVCA& dref)
    {}          
};

NVCRA GetATemp()
{       
   return NVCRA(5);
} 

NVCRA GetACopy()
{
   NVCRA ret(5);
   ...
   return ret;  
}

int main()
{ 
    //This call will be elided allays and invoke the single param constructor 
    NVCRA A = GetATemp();
    //This call will be a traditional copy the complier may elide this 
    // if so the work will be done inline 
    NVCRA B = GetACopy();

}

In this case move semantics play no part and the only difference from C++03 in c++11 is that rather than the compiler being allowed to elide they are required to elide.

So Question 1. Under what cases am I guaranteed a copy constructor will or will not be elided.

Question 2. Is there a way to force the compiler to not elide.

Question 3. Is there any logical reason why I would not want the compiler to do so, assuming that you have logically consistent copy operations.

Question 4. If I define a move constructor, a move will occur in cases where the copy is not elided anyway. Should this effect my design of classes.

like image 564
rerun Avatar asked Dec 12 '22 05:12

rerun


1 Answers

  1. Eliding copies and moves is always an optional optimization and the standard offers no guarantees on when it will be done. Elision is different from the compiler choosing move over copy. The language guarantees when move construction or move assignment is chosen according to its normal overload resolution rules.

  2. Some compilers offer a flag to turn elision off. gcc and clang have -fno-elide-constructors. MSVC does not have a specific option, but disabling optimization may avoid some elisions (but some can't be turned off no matter what, such as the copy in Foo x = 1;)

  3. I don't know of any reason not to elide copies/moves in production builds.

  4. Some people had recommended not relying on the 'return value optimizaiton' when returning 'heavy' classes, because RVO isn't guaranteed. Personally I just verified that my compilers were good about it and went ahead with it. Now that objects can be moved you no longer need to worry about whether a compiler supports such optimizations, because even if it doesn't you'll still get moves instead of copies.

like image 124
bames53 Avatar answered Dec 22 '22 00:12

bames53