Home >Backend Development >C++ >Why Is the Move Constructor Not Called in C 11 When Copy Elision Is Enabled?

Why Is the Move Constructor Not Called in C 11 When Copy Elision Is Enabled?

DDD
DDDOriginal
2024-11-06 09:46:02309browse

Why Is the Move Constructor Not Called in C  11 When Copy Elision Is Enabled?

C 11 Move Constructor Not Called, Default Constructor Preferred

When working with classes in C , it's expected that move constructors will be utilized for efficient resource transfer. However, in some cases, the default constructor may be unexpectedly chosen instead.

Problem Statement

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>

With the sample 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 expected output is:

ctor
test
copy
test
ctor move test

However, the last line unexpectedly outputs "ctor" instead of "move."

Explanation

According to the C 11 standard, move constructors should be called in certain situations. In this case, a move should occur when constructing z with X("test"). However, the default constructor is called instead.

This behavior is due to copy elision, an optimization technique that allows the compiler to directly construct a temporary into a target without performing a copy or move operation. This optimization applies in cases where the compiler determines that the copy/move operation is unnecessary and can be elided.

In the given scenario, the compiler considers the temporary X("test") a candidate for copy elision, as it is automatically created and destroyed within the same expression. Consequently, it omits the move operation and constructs z directly using the temporary's data, resulting in the call to the default constructor.

Conclusion

Copy elision can lead to unexpected behavior when working with move constructors, as it can prevent the move constructor from being invoked in situations where it is expected. Compilers may apply copy elision based on their optimization heuristics, which can vary between compilers and optimization settings. It's important to be aware of copy elision and its potential impact on program behavior.

The above is the detailed content of Why Is the Move Constructor Not Called in C 11 When Copy Elision Is Enabled?. 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