Heim  >  Artikel  >  Backend-Entwicklung  >  Warum wird der C 11 Move-Konstruktor nicht aufgerufen, wenn ein temporäres Objekt zum Initialisieren eines anderen Objekts verwendet wird?

Warum wird der C 11 Move-Konstruktor nicht aufgerufen, wenn ein temporäres Objekt zum Initialisieren eines anderen Objekts verwendet wird?

Mary-Kate Olsen
Mary-Kate OlsenOriginal
2024-11-05 05:06:02946Durchsuche

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

C 11 Move-Konstruktor nicht aufgerufen, Standardkonstruktor bevorzugt

Beschreibung:
Beim Arbeiten mit Move-Semantik in C 11 ist dies möglich um auf Szenarien zu stoßen, in denen der Verschiebungskonstruktor unerwartet zugunsten des Standardkonstruktors übersprungen wird. In diesem Artikel wird dieses Problem untersucht, die zugrunde liegenden Gründe untersucht und Lösungen bereitgestellt.

Problem:
Betrachten Sie die folgende Klasse X mit Konstruktoren, die Nachrichten ausgeben:

<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 der unten bereitgestellten Beispielverwendung erstellen wir drei Objekte:

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

Anstelle der erwarteten Ausgabe, die zeigt, dass der Verschiebungskonstruktor für z aufgerufen wird, wird jedoch stattdessen der Standardkonstruktor verwendet.

Standardkonformität:
Gemäß dem C 11-Standard (§12.8.32) sollte die Verschiebungssemantik nach Möglichkeit der Kopiersemantik vorgezogen werden. In diesem Fall sollte der Verschiebungskonstruktor also tatsächlich für z aufgerufen werden.

Erklärung des Verhaltens:
Das beobachtete Verhalten ist auf eine Compileroptimierung namens Kopierelision. Mit C 11 können Compiler in bestimmten Situationen das Kopieren/Verschieben von Objekten unterlassen, um die Leistung zu verbessern. Eine dieser Situationen ist, wenn ein temporäres Objekt in ein Objekt mit demselben cv-unqualifizierten Typ kopiert/verschoben würde.

In der letzten Zeile unseres Beispielcodes erstellt X("test") ein temporäres X Objekt und es hat denselben cv-unqualifizierten Typ wie das Ziel (z). Daher kann der Compiler auf die Kopier- und Verschiebungskonstruktoren verzichten und das temporäre Objekt direkt in z konstruieren, ohne einen der beiden Konstruktoren aufzurufen.

Lösung:Um den Verschiebungskonstruktor zu erzwingen aufgerufen, können wir std::move() verwenden, um explizit anzugeben, dass die Verschiebung stattfinden soll:

<code class="cpp">X z( std::move(X("test")) );</code>
Mit dieser Änderung wird die erwartete Ausgabe erzeugt, die die Beteiligung des Verschiebungskonstruktors bestätigt.

Das obige ist der detaillierte Inhalt vonWarum wird der C 11 Move-Konstruktor nicht aufgerufen, wenn ein temporäres Objekt zum Initialisieren eines anderen Objekts verwendet wird?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn