Integrierte Datentypen durch (Copy-)Konstruktor initialisiren
-
Hi,
wie wir ja alle wissen ist es sinnvoller Objekte durch den Copykonstruktor schon bei der Deklaration zu initialisieren anstatt ihnen nach der Deklaration einen Wert zuzuweisen. Jetzt war mir, als hätte ich irgendwo mal gelesen, dass es "good practice" wäre dies auch mit integrierten Datentypen zu tun.
//besser so int i(5); //als so int j = 5;Mir ist aber entfallen, wie die Begründung lautete und die einzige, die mir so durch Überlegen einfallen würde, wäre es einfach aus Konsistenzgründen zu tun.
Ich meine, dass ich dass in einer recht vertrauenswürdigen Quelle gelesen habe, Meyers Buch oder Stroustrups FAQ, irgendwie sowas. Leider finde ich besagte Stelle nicht mehr.Da mir der Grund damals aber so einleuchtend erschien, dass ich mir diesen Style angewöhnt habe und vorhin auf die Frage, warum ich es so schreibe keine wirkliche Antwort geben konnte, würde ich besagte Stelle gerne wiederfinden. Weiß vielleicht jemand von euch, wo ich das gelesen haben könnte? Oder wüsste jemand, was die Gründe gewesen sein könnten, diesen Style zu empfehlen?
-
T o(x);ist äquivalent zuT o = x;. (Mit explicit wird das natürlich ein bisschen anders.)
-
Kunz schrieb:
wie wir ja alle wissen ist es sinnvoller Objekte durch den Copykonstruktor schon bei der Deklaration zu initialisieren anstatt ihnen nach der Deklaration einen Wert zuzuweisen. Jetzt war mir, als hätte ich irgendwo mal gelesen, dass es "good practice" wäre dies auch mit integrierten Datentypen zu tun.
//besser so int i(5); //als so int j = 5;Da bin ich anderer Meinung. Ich finde die erste Syntax nicht besonders leserlich. Für fundamentale und andere POD-Typen macht es auch überhaupt keinen Unterschied. Formal ist das erste eine "direct initialization" und das zweite eine "copy initialization". Eine Zuweisung findet hier nirgendswo statt. Zuweisen gibt's nur, wenn es das Objekt schon gibt und verändert werden soll.
In generischem Code, also in Code, wo der Typ von ein oder mehreren Template-Parametern abhängt, ist das was anderes. Da benutze ich auch schonmal die erste Syntax, wenn mir danach ist.
Kunz schrieb:
Mir ist aber entfallen, wie die Begründung lautete und die einzige, die mir so durch Überlegen einfallen würde, wäre es einfach aus Konsistenzgründen zu tun.
Ich meine, dass ich dass in einer recht vertrauenswürdigen Quelle gelesen habe, Meyers Buch oder Stroustrups FAQ, irgendwie sowas. Leider finde ich besagte Stelle nicht mehr.In Stroustrup's Buch steht irgendwo so etwas drin wie "ich mag die T x = blah; Syntax."
Wenn blah auch vom Typ T ist, garantiert der C++ Standard, dass keine temporäre Kopie angelegt wird. In diesem Fall gibt es keine Unterschiede bzgl Ausführungsgeschwindigkeit. Falls der Typ von blah nicht T ist, wird "im Prinzip" ein temporäres Objekt vom Typ T erzeugt (entweder über impliziten Konstruktor oder Konvertierungsoperator) und anschließend das Objekt x mit dem anderen Temp-Objekt konstruiert (copy ctor). Praktisch erzeugen viele Compiler kein solches temporäres Objekt. Das darf nämlich wegoptimiert werden.
Gruß,
SP
-
Das würde aber eher bedeuten, dass ich genau das Gegenteil gelesen haben müsste. Ach es ärgert mich total, dass dich die Quelle nicht mehr finden kann.

rüdiger schrieb:
T o(x);ist äquivalent zuT o = x;. (Mit explicit wird das natürlich ein bisschen anders.)Das stimmt so nicht. Wie Sebastian schon richtig schrieb, darf ein temp. Objekt wegoptimiert werden, aber laut Standard darf das nicht dazu führen, dass ungültiger Code kompiliert wird.
class Test { public: Test(int i) {}; private: Test(const Test&); }; int main() { Test foo(1); //kompiliert Test bar = 1; //Kompilerfehler! }Sebastian Pizer schrieb:
In generischem Code, also in Code, wo der Typ von ein oder mehreren Template-Parametern abhängt, ist das was anderes. Da benutze ich auch schonmal die erste Syntax, wenn mir danach ist.
Das sollte man auch, wer garantiert dir, dass du nicht eine Klasse wie im obigen Beispiel hast?
Na ja, ich suche weiter nach der Quelle und bin für weitere Hinweise und Meinungen dankbar

-
Kunz schrieb:
Das sollte man auch, wer garantiert dir, dass du nicht eine Klasse wie im obigen Beispiel hast?
Was spielt das für eine Rolle? Ach, du meinst wegen dem expliziten Konstruktor? Ja, das ist eigentlich der einzige Grund, warum ich die erste Syntax nehmen würde. Sonst finde ich die Kopier-Initialisierung "hübscher".
Gruß,
SP
-
Sebastian Pizer schrieb:
Sonst finde ich die Kopier-Initialisierung "hübscher".
Geht mir auch so. Das Vorhandensein eines nicht-expliziten Konstruktors legt nahe, dass es sich um eine Konvertierung/Kopie eines kompatiblen Objekts handelt. Nach der Anweisung stehen links und rechts zumindest semantisch die gleichen Werte. Also
std::complex<int> c = 1; // komplexe Zahl 1im Gegensatz zu
std::vector<int> v(1); // Container mit einem ElementAusserdem bin ich kein Fan von vielen Klammern. Auch in If-Abfragen nutze ich meistens die Operatorpriorität von && und || aus und klammere nur, was nötig ist und zu besserer Erkennbarkeit (für mich) beiträgt.