Returning a Named Object by Value from a Function and Implied Move Rule
Consider a situation where an object of a generic class is returned by value from a function. In Example 1:
<code class="cpp">class test { public: test() { printf(" test()\n"); } test(test&& s) { printf(" test(test&& s)\n"); } test& operator=(test e) { printf(" test& operator=( test e)\n"); return *this; } }; test Some_thing() { test i; return i; }</code>
The output is:
test() test(test&& s)
In this example, the constructor test() is called for the LValue object i created in the function, and the move constructor test(test&& s) is called when the object i is returned by value, since the expression return i is an rvalue reference.
In Example 2, the copy constructor test(test& z) is provided, but the move constructor is not synthesized by the compiler:
<code class="cpp">class test { public: test() { printf(" test()\n"); } test(test& z) { printf(" test(test& z)\n"); } test& operator=(test e) { printf(" test& operator=( test e)\n"); return *this; } }; test Some_thing() { test i; return i; }</code>
The output remains the same as in Example 1:
test() test(test& z)
The copy constructor is used because there is no available move constructor.
In Example 3, the move constructor is explicitly deleted:
<code class="cpp">class test { public: test(test&& z) = delete; // Deleted move constructor test() { printf(" test()\n"); } test(test& z) { printf(" test(test& z)\n"); } test& operator=(test e) { printf(" test& operator=( test e)\n"); return *this; } }; test Some_thing() { test i; return i; }</code>
Trying to compile this code will result in an error, as the deleted move constructor means that no move operation can be performed.
In Example 4, even though the move constructor is deleted, the code compiles and runs:
<code class="cpp">class test { public: test(test&& z) = delete; test() { printf(" test()\n"); } test(test& z) { printf(" test(test& z)\n"); } test& operator=(test e) { printf(" test& operator=( test e)\n"); return *this; } }; int main() { test u; test r(u); // Copy constructor is used return 0; }</code>
Output:
test() test(test& z)
In this example, r(u) creates a new object r by copying the object u. The move constructor is not used because it's deleted, and the copy constructor is used instead.
The key takeaway is that whether the move constructor is used or not depends on the availability of a viable move constructor and the rules for overload resolution. If the move constructor is available and viable, it may be used for initializing the returned value from a function, even if the expression used to return the value is an LValue.
The above is the detailed content of When is the Move Constructor Used for Returning Named Objects by Value in C ?. For more information, please follow other related articles on the PHP Chinese website!