Ich habe darauf hier
geantwortetEine Sache, die ich hier in die Antwort einfüge: Keiner benutzt einen Zuweisungsoperator .
Kurze Erklärung für die stringspezifische Sache. std::string
hat einen Konstruktor, der ein Argument akzeptiert, das char const*
akzeptiert:
Nun sehen Sie, dass ein Konstruktor einen Zeiger auf Zeichen hat. Damit kann ein String-Literal akzeptiert werden. Ich denke, der folgende Fall ist dann offensichtlich:
%Vor% Er ruft den Konstruktor direkt auf und initialisiert dabei s
. Dies wird direkte Initialisierung genannt.
Die andere Art der Initialisierung einer Variablen wird Kopierinitialisierung genannt. Der Standard sagt für den Fall der Kopierinitialisierung, wo der Initialisierer nicht den Typ des Objekts hat, das initialisiert wird, der Initialisierer in den richtigen Typ konvertiert wird.
%Vor%Zuerst geben wir die Typen an
s
hat den Typ std :: string "hello"
ist ein Array, das in diesem Fall wieder wie ein Zeiger behandelt wird. Wir werden es daher als char const*
betrachten. Der Compiler sucht nach zwei Möglichkeiten, die Konvertierung durchzuführen.
std::string
? Er erstellt eine temporäre std::string
auf eine der Arten, die dann verwendet wird, um das Objekt s
zu initialisieren, indem Sie std::string
's Kopierkonstruktor verwenden. Und es sieht std::string
hat einen Konvertierungskonstruktor, der den Initialisierer akzeptiert. Es benutzt es also. Am Ende ist es tatsächlich dasselbe wie
Beachten Sie, dass das Formular, das in Ihrem Beispiel verwendet wird, das alles ausgelöst hat
%Vor% definiert eine implizite Konvertierung . Sie können den Konstruktor mit dem char const*
als explizit für Ihre Typen markieren, wenn Sie sich über die Initialisierungsregeln für Ihre Sachen wundern, und es nicht erlauben wird, den entsprechenden Konstruktor als -Konstruktor zu verwenden mehr:
Damit ist es jetzt (und an verschiedenen anderen Stellen) verboten, es mit copy initialization
und char const*
zu initialisieren!
Nun, das war, wenn der Compiler die Elision von Provisorien an verschiedenen Stellen nicht unterstützt. Der Compiler darf annehmen, dass ein Kopierkonstruktor in diesem Kontext kopiert, und kann die zusätzliche Kopie der temporären Zeichenfolge entfernen und stattdessen die temporäre std :: string direkt in das initialisierte Objekt einbauen. Der Kopierkonstruktor muss jedoch insbesondere zugänglich sein. Daher ist die Kopierinitialisierung ungültig, wenn Sie dies tun
%Vor%Jetzt ist eigentlich nur der direkte Initialisierungsfall gültig.
Kompiliere beide, sieh dir den Assembler an. Der erste ist eine weniger Anweisung ...
%Vor%... aber das ist ein Artefakt, weil es der erste war, den der Compiler gesehen hat. Ändern Sie den Code, indem Sie die Reihenfolge wechseln:
%Vor%... und siehe da, die Sekunde ist eine Anweisung weniger.
Wir sehen auch, dass dieser Compiler (Microsoft VC ++ 2005, Release-Einstellungen) für beide Versionen den gleichen Assembler generiert hat. Es macht also keinen Unterschied in diesem Compiler, und Sie können es beweisen.
Der einzige wirkliche Unterschied besteht darin, dass der erste den Kopierkonstruktor technisch benötigt, aber der Compiler darf ihn verwenden, damit die Effizienz in beiden Fällen identisch ist.
Der erste erfordert jedoch, dass der Kopierkonstruktor zugänglich ist (d. h. nicht privat), selbst wenn er nicht tatsächlich verwendet wird.
Die anderen Antworten sind alle korrekt, aber denken Sie bitte auch daran, dass das wahrscheinlich keine Rolle spielt. Es wird selten, sehr selten, unglaublich selten, dass die Effizienz der String-Initialisierung Auswirkungen auf Ihr Programm hat Geschwindigkeit sogar um einen Bruchteil einer Sekunde.
Die Frage selbst ist eine Spaß , weil sie die Operationen von C ++ - Konstruktoren und -Zuordnungen zeigt, aber in der Praxis, wenn Sie Zeit damit verbringen, diese zu optimieren (und die Veröffentlichung auf SO ist Beweis genug) du bist ..) du kippst wirklich Windmühlen.
Es ist besser, die Ablenkung zu vermeiden und sich anderswo zu bemühen.
Tags und Links c++ constructor initialization