Home >Backend Development >C++ >Why is the C 11 Move Constructor Not Called When a Temporary Object is Used to Initialize Another Object?

Why is the C 11 Move Constructor Not Called When a Temporary Object is Used to Initialize Another Object?

Mary-Kate Olsen
Mary-Kate OlsenOriginal
2024-11-05 05:06:021009browse

Why is the C  11 Move Constructor Not Called When a Temporary Object is Used to Initialize Another Object?

C 11 Move Constructor Not Called, Default Constructor Preferred

Description:
When working with move semantics in C 11, it's possible to encounter scenarios where the move constructor is unexpectedly skipped in favor of the default constructor. This article explores this issue, examines the underlying reasons, and provides solutions.

Problem:
Consider the following class X with constructors that output messages:

<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>

In the sample usage provided below, we create three objects:

<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>

However, instead of the expected output showing the move constructor being called for z, the default constructor is used instead.

Standard Conformity:
According to the C 11 standard (§12.8.32), move semantics should be preferred over copy semantics whenever possible. So, the move constructor should indeed be called for z in this case.

Explanation of Behavior:
The observed behavior is due to a compiler optimization called copy elision. C 11 allows compilers to omit copying/moving objects in certain situations to improve performance. One of these situations is when a temporary object would be copied/moved to an object with the same cv-unqualified type.

In the last line of our sample code, X("test") creates a temporary X object and it has the same cv-unqualified type as the target (z). Therefore, the compiler is allowed to elide the copy and move constructors, directly constructing the temporary object into z without invoking either constructor.

Solution:
To force the move constructor to be called, we can use std::move() to explicitly indicate that the move should take place:

<code class="cpp">X z( std::move(X("test")) );</code>

With this modification, the expected output is produced, confirming the involvement of the move constructor.

The above is the detailed content of Why is the C 11 Move Constructor Not Called When a Temporary Object is Used to Initialize Another Object?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn