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?
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.
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!