Consider the following class:
<code class="cpp">class X { public: explicit X(char* c) { cout << "ctor" << endl; init(c); }; X(X& lv) { cout << "copy" << endl; init(lv.c_); }; X(X&& rv) { cout << "move" << endl; c_ = rv.c_; rv.c_ = nullptr; }; const char* c() { return c_; }; private: void init(char *c) { c_ = new char[strlen(c)+1]; strcpy(c_, c); }; char* c_; };</code>
And its usage:
<code class="cpp">X x("test"); cout << x.c() << endl; X y(x); cout << y.c() << endl; X z( X("test") ); cout << z.c() << endl;</code>
The output is:
ctor test copy test ctor <-- why not move? test
In VS2010, using default settings, one would expect the last object (z) to be move-constructed instead of default-constructed. Using X z( move(X("test")) ) results in the expected output: ctor move test. Could this be a case of NRVO?
Should the move constructor be called according to the C 11 standard? If so, why isn't it called?
The observed behavior is due to copy elision. The compiler can directly construct a temporary into a target it is to be copied/moved into, thus omitting the copy/move constructor and destructor calls.
The situations where copy elision can be applied are outlined in §12.8.32 of the C 11 standard:
In this case, the compiler is able to elide the copy or move operation between the temporary X("test") and the target z, resulting in the observed behavior.
The above is the detailed content of Why Doesn't My C 11 Move Constructor Get Called in This Case?. For more information, please follow other related articles on the PHP Chinese website!