C 11 Move-Konstruktor nicht aufgerufen, Standardkonstruktor bevorzugt
Bei der Arbeit mit Klassen in C wird erwartet, dass Move-Konstruktoren verwendet werden effizienter Ressourcentransfer. In einigen Fällen kann jedoch unerwartet stattdessen der Standardkonstruktor ausgewählt werden.
Problemstellung
Betrachten Sie die folgende Klasse:
<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>
Mit die Beispielverwendung:
<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>
Die erwartete Ausgabe ist:
ctor test copy test ctor move test
Die letzte Zeile gibt jedoch unerwartet „ctor“ anstelle von „move“ aus.
Erklärung
Gemäß dem C 11-Standard sollten Bewegungskonstruktoren in bestimmten Situationen aufgerufen werden. In diesem Fall sollte beim Konstruieren von z mit X("test") eine Verschiebung erfolgen. Stattdessen wird jedoch der Standardkonstruktor aufgerufen.
Dieses Verhalten ist auf die Kopierelision zurückzuführen, eine Optimierungstechnik, die es dem Compiler ermöglicht, ein temporäres Objekt direkt in ein Ziel zu konstruieren, ohne einen Kopier- oder Verschiebevorgang auszuführen. Diese Optimierung gilt in Fällen, in denen der Compiler feststellt, dass der Kopier-/Verschiebevorgang unnötig ist und eliminiert werden kann.
Im gegebenen Szenario betrachtet der Compiler das temporäre X („test“) als Kandidaten für die Kopierelision. da es automatisch innerhalb desselben Ausdrucks erstellt und zerstört wird. Folglich wird die Verschiebungsoperation weggelassen und z direkt unter Verwendung der temporären Daten erstellt, was zum Aufruf des Standardkonstruktors führt.
Schlussfolgerung
Kopieren kann zu unerwarteten Ereignissen führen Verhalten bei der Arbeit mit Verschiebungskonstruktoren, da es verhindern kann, dass der Verschiebungskonstruktor in Situationen aufgerufen wird, in denen dies erwartet wird. Compiler können die Kopierelision basierend auf ihren Optimierungsheuristiken anwenden, die je nach Compiler und Optimierungseinstellungen variieren können. Es ist wichtig, sich der Kopierelision und ihrer möglichen Auswirkungen auf das Programmverhalten bewusst zu sein.
Das obige ist der detaillierte Inhalt vonWarum wird der Move-Konstruktor in C 11 nicht aufgerufen, wenn die Kopierelision aktiviert ist?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!