2015-10-12 14 views
14

Im folgenden Code sind pS und s.pS garantiert in der letzten Zeile gleich? Mit anderen Worten, in der Aussage S s = S();, kann ich sicher sein, dass eine temporäre S wird nicht gebaut werden?In S s = S() ist garantiert, dass keine temporäre erstellt wird?

#include <iostream> 
using namespace std; 

struct S 
{ 
    S() { pS = this; } 
    S* pS; 
}; 

int main() 
{ 
    S s = S(); 
    S* pS = &s; 
    cout << pS << " " << s.pS << endl; 
} 

In jedem Compiler habe ich dies in pS == s.pS getestet, aber ich bin nicht ausreichend vertraut mit dem Standard der Lage sein, mich zu überzeugen, dass dies gewährleistet ist.

+2

Nein - es ist eine temporäre, die vielleicht optimiert werden könnte –

+0

Nach meinem besten Wissen können Sie davon ausgehen, dass es RVO sein wird und nur sorgen müssen, wenn Sie besondere Umstände haben, die besondere Behandlung oder Leistungsgarantien erfordern. Ansonsten ist dies praktisch gewährleistet und sollte genutzt werden. – Mordachai

+2

@Mordachai Das hat nichts mit RVO zu tun. Das R steht für Rückkehr. Es gibt keine Rückkehr hier. – Barry

Antwort

16

NO

Der Compiler ist nicht verpflichtet Kopie elision zu tun. Die Norm legt einfach, dass, [class.copy]:

Wenn bestimmte Kriterien erfüllt sind, eine Implementierung erlaubt ist das Kopieren/Verschieben Bau eines Klassenobjekts auslassen [...]

Ich kann Kopie Elision über -fno-elide-constructors deaktivieren, und dann werden die beiden Zeiger definitiv anders sein. Zum Beispiel:

$g++ -std=c++11 -Wall -pedantic -fno-elide-constructors -Wall -Wextra main.cpp && ./a.out 
0x7fff5a598920 0x7fff5a598930 

Und im allgemeinen Fall, wenn wir S(S&&) = delete hinzufügen, dann wird der obige Code würde kompiliert nicht einmal.

+0

Ich dachte C++ 11 oder 13 machte dies zwingend. Und trotzdem - ich glaube, es ist in der Kategorie der "praktisch garantiert" und "Best Practices" nicht mehr darüber zu sorgen (mit dem üblichen Vorbehalt von: wenn Sie Leistungstests durchführen, und feststellen, dass dies ein tatsächliches Problem ist ein Hot-Code-Pfad, dann und nur dann würden Sie manuell in die Optimierung dieses manuell einbeziehen) ... – Mordachai

+0

@Mordachai Nope. Die von mir zitierte Formulierung stammt aus N4527. – Barry

+2

@Mordachai Es ist absolut nicht "Best Practice", sich nicht darum zu kümmern! – Pixelchemist

11

Die meisten Compiler führen die so genannte copy/move elision aus, die vom C++ - Standard angegeben wird. Aber es ist nicht garantiert. Zum Beispiel können Sie mit -fno-elide-constructors in gcc kompilieren und Sie werden alle Konstruktoren in ihrer ganzen Pracht sehen.

Live example on Coliru

5

Es kann nicht garantiert werden, dass es keine vorübergehenden Probleme gibt. Aber die Big Three Compiler werden es optimieren (sogar mit dem -O0 Switch).

Um keine vorübergehende Garantie überhaupt nur schreiben:

int main() 
{ 
    // ... 
    S s{}; 
    // ... 
} 

Oder einfach S s;.