Is the "move elision" guaranteed in C 17? Let me explain what I mean by that. In almost every article on what C 17 has introduced, one can find the term: "guaranteed copy elision for RVO" which is kinda self-explanatory. But what about move construction?
Let's look at the code below, it's simple there is a non-copyable type, and two functions, one takes NonCopyable parameter by value, and the second one takes it by rvalue reference.
#include <iostream>
struct NonCopyable
{
NonCopyable() = default;
NonCopyable(const NonCopyable&) = delete;
NonCopyable(NonCopyable&& other) noexcept
{
std::cout << "Move ctor\n";
}
};
void func_by_value(NonCopyable cp)
{
auto x = std::move(cp);
}
void func_by_rvalue_ref(NonCopyable&& cp)
{
auto x = std::move(cp);
}
int main()
{
std::cout << "Pass by value:\n";
func_by_value(NonCopyable());
std::cout << "\nPass by rvalue_ref\n";
func_by_rvalue_ref(NonCopyable());
}
I compiled it two times using GCC(trunk) using the following flags, and the results are slightly different.
(1) -O0 -std=c 11 -fno-elide-constructors
Program output: Pass by value: Move ctor Move ctor Pass by rvalue_ref Move ctor
(2) -O0 -std=c 17 -fno-elide-constructors
Program output: Pass by value: Move ctor Pass by rvalue_ref Move ctor
So my question is - what has changed that the move constriction was elided when using C 17? Compiler explorer
CodePudding user response:
Since C 17 mandatory elision of copy/move operations was introduced:
Under the following circumstances, the compilers are required to omit the copy and move construction of class objects, even if the copy/move constructor and the destructor have observable side-effects. The objects are constructed directly into the storage where they would otherwise be copied/moved to. The copy/move constructors need not be present or accessible:
...
In the initialization of an object, when the initializer expression is a prvalue of the same class type (ignoring cv-qualification) as the variable type:
T x = T(T(f())); // only one call to default constructor of T, to initialize x
In the initialization of the parameter cp
from the prvalue NonCopyable()
, the move construction is required to be elided. Note that mandatory copy elision works for both copy operation and move operation.