C++ Pendant zu Java Objekt Referenz
-
@CppConst sagte in C++ Pendant zu Java Objekt Referenz:
Wie sieht es nun mit der Rückgabe eines Objektes in C++ aus, wenn dieses in der Methode erst erzeugt wird, ich aber keine Kopie haben möchte?
Kommt drauf an... ich würde in den meisten Fällen einfach ein Return machen und mich auf RVO verlassen (https://en.wikipedia.org/wiki/Copy_elision#Return_value_optimization).
Man kann auch smart pointer zurück geben, wenn aus irgendeinem Grund nötig.
-
Und wenn man sich nicht auf RVO verlassen möchte, was kann man dann empfehlen?
-
Deine Fragen sind viel zu allgemein. Bevor einem ein Profiler nicht gesagt hat daß es ein Flaschenhals ist macht man sich über sowas sowieso keine Gedanken.
-
@CppConst sagte in C++ Pendant zu Java Objekt Referenz:
Und wenn man sich nicht auf RVO verlassen möchte, was kann man dann empfehlen?
Sich auf RVO zu verlassen.
-
Ist halt nicht einfach, wenn man von Java auf C++ umsteigt und bei mir in Java werden haufenweise Objekte in Methoden erzeugt und dann einfach zurückgegeben. Und bei C++ habe ich eben gelesen, dass es da zu Kopien kommen kann. Das versuche ich im Vorfeld schon sicher zu eliminieren und dachte da gibt es was Allgemeines für.
-
@CppConst sagte in C++ Pendant zu Java Objekt Referenz:
Das versuche ich im Vorfeld schon sicher zu eliminieren
Ja. Lass das. Das ist vergebene Liebesmüh'. Schreib' schönen(tm) Code.
-
Ok, dann kümmere ich mich darum wenn es Probleme gibt und erzeuge erstmal einfach einen std::string und geben den so wie er ist mit return zurück.
-
Gute Idee.
-
Wenn es um String geht... https://www.c-plusplus.net/forum/topic/347040/einen-string-an-eine-funktion-übergeben
-
@Helmut-Jakoby Es geht um Rückgabe. Aber, gratuliere, du hast deinen Werbelink wieder erfolgreich angebracht.
-
Damit RVO greifen kann, muss meine Objekt aber einen Move Konstruktor haben, oder?
-
@CppConst sagte in C++ Pendant zu Java Objekt Referenz:
Damit RVO greifen kann, muss meine Objekt aber einen Move Konstruktor haben, oder?
Nein.
Move ist auch Arbeit, wenn auch oft weniger als eine Kopie. Aber wenn es geht, ist "gar nichts tun" besser als move. Move passiert, wenn "nichts tun" nicht geht.
Siehe auch https://youtu.be/hA1WNtNyNbo
-
Bzw. s. Copy elision
-
@CppConst sagte in C++ Pendant zu Java Objekt Referenz:
Damit RVO greifen kann, muss meine Objekt aber einen Move Konstruktor haben, oder?
Bei RVO + copy-elision wird das Objekt direkt dort erstellt wo es dann nach dem Funktionsaufruf "weiterleben" soll.
Foo makeFoo() { Foo f{"blah"}; // 1 f.something(1); f.somethingElse(1, 2, 3); return f; // Hier KEIN std::move() - mit move würde man NRVO _verhindern_ } void fun() { Foo foo{makeFoo()}; // 2 }
Das Objekt das in (1) erstellt wird, wird also direkt im Speicher der Variable von Zeile (2) erstellt. Hier wird weder ein Move-Konstruktor noch ein Copy-Konstruktor verwendet.
-
Danke für die genaue Erklärung, so langsam begreife ich es. Ist nicht so einfach C++ richtig zu verstehen. Ich habe zwar schon einige Sachen mit C++ gemacht, habe mir allerdings über solche Dinge keine Gedanken gemacht, bis ich so ein CppCon Video gesehen hatte, wo es darum ging wie man Overhead vermeiden kann, dann kamen die Fragen und nun möchte ich C++ besser kennen lernen.
-
Ergänzung:
Foo makeFoo() { Foo f{"blah"}; // 1 f.something(1); f.somethingElse(1, 2, 3); return f; // Hier KEIN std::move() - mit move würde man NRVO _verhindern_ }
Tatsächlich garantierte der Standard vor guaranteed copy elision (also vor C++17) ab C++11, dass der identifier
f
ein rvalue ist. D.h.move(f)
war implizit. Es haette also schon rein technisch niemals geholfen, das zu schreiben (abgesehen davon, dass NRVO lange vor guaranteed copy elision implementiert war).
-
Spannend wird es nur hier:
Foo makeFoo(bool condition) { Foo f1{"blah"}; Foo f2{"blubberdieblubb"}; // [code...] // a) return condition ? f1 : f2; // b) return std::move(condition ? f1 : f2); }
Hier ist rechts ja ein ?-:-Konstrukt. Mit so einer Konstruktion verbaut man sich das automatische move.
-
Also theoretisch könnte man einen absoluten Grossteil der Verwendungen eines automatischen Objektes in return statements durch einen Move ersetzen. Es gibt aber eben auch Ausnahmen (überwiegend realitätsferner Natur...) und deshalb ist es nur fuer simple Identifier gegeben.
-
@Columbo sagte in C++ Pendant zu Java Objekt Referenz:
Es haette also schon rein technisch niemals geholfen, das zu schreiben
Richtig. Ich hab das Kommentar bloss dazugeschrieben weil es in dem Fall nicht nur unnütz ist sondern sogar schadet.
-
@hustbaer ich weiss, deshalb ja auch als "Ergänzung"