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.
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.
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;
)
I don't know of any reason not to elide copies/moves in production builds.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With