Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Julién

Alter Hase

  • »Julién« ist der Autor dieses Themas

Beiträge: 717

Wohnort: Bayreuth

Beruf: Student | Hilfswissenschaftler in der Robotik

  • Private Nachricht senden

1

20.06.2015, 22:49

C++ | Rückgabe von Objekten?

Da ich gerade eine Vektorklasse implementieren darf (muss) und auf ein Problem gestoßen bin,
dachte ich, dass ich mir was bei Davids TriBase abschauen könnte.
Sogleich habe ich eine interessante Lösung zu meinem Problem gefunden.

Die Vektorklasse überladet die Operatoren und gibt einen Vektor zurück:

C-/C++-Quelltext

1
2
3
4
5
...
{
    return Vektor(x, y, z);
}
...


Wieso funktioniert das? Soweit ich das verstehe ist das Objekt, das erzeugt wird, eine lokale Instanz auf dem Stack,
die nachdem Funktionsaufruf wieder gelöscht/überschrieben wird.
Oder habe ich schon wieder etwas vergessen, das C++ betrifft?

Mit freundlichen Grüßen,
Julien
I write my own game engines because if I'm going to live in buggy crappy filth, I want it to me my own - Ron Gilbert

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Julién« (20.06.2015, 22:55)


DeKugelschieber

Community-Fossil

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

2

20.06.2015, 23:12

Das Objekt wird kopiert.

H5::

Treue Seele

Beiträge: 368

Wohnort: Kiel

  • Private Nachricht senden

3

20.06.2015, 23:46

Nein, zumindest wenn es sich um einen c++11 => Compiler handelt findet hier Move Semantik Anwendung (Return Value Optimization (RVO)). (Move Semantics)
:love: := Go;

DeKugelschieber

Community-Fossil

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

4

21.06.2015, 00:04

Klar wird das wegoptimiert. Aber vom Verständnis her.

Julién

Alter Hase

  • »Julién« ist der Autor dieses Themas

Beiträge: 717

Wohnort: Bayreuth

Beruf: Student | Hilfswissenschaftler in der Robotik

  • Private Nachricht senden

5

21.06.2015, 00:20

Also, das bedeutet, dass der Zuweisungsoperator gleich aufgerufen wird?

Ich bin bei diesem Beispiel etwas verwirrt. Für mich ist das Objekt nach dem "return" eigentlich weg.
Wie wird es kopiert, Kugelschieber?#

P.S.: Rule of Three?
P.P.S: Ich lese mich mal noch mal in den C++ Programmierer rein. Anscheinend habe ich etwas grundlegendes vergessen.
I write my own game engines because if I'm going to live in buggy crappy filth, I want it to me my own - Ron Gilbert

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Julién« (21.06.2015, 00:33)


BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

6

21.06.2015, 00:41

Das ist auch nicht anders als "return 5;" oder "return true;". Oder "return my_string;".
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

H5::

Treue Seele

Beiträge: 368

Wohnort: Kiel

  • Private Nachricht senden

7

21.06.2015, 00:49

Das Objekt wird wahrscheinlich nicht kopiert, es wird verschoben und ändert seinen Besitzer. Bei einer Kopie wird der Kopierkonstruktor aufgerufen. Dass wird hier nicht der Fall sein. Movesemantik ist keine Compileroptimierung sondern ein Teil der Sprache, sie ist nicht unsichtbar.

Understanding C++11 move semantics

Kopieren wird ja oft als so böse dargestellt, und ist auch recht ungünstig bei großen Objekten. Wenn man jetzt denkt hier würde Kopiert, so ist man sicher versucht ein nicht mehr vorhandenes Problem zu Optimieren/Lösen. Dies führt unnötiger weise zu unschönem Code. Sollte man jedoch erwarten, dass ein Kopierkonstruktor aufgerufen wird, so führt es sogar zu unerwartetem Verhalten.
:love: := Go;

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

8

21.06.2015, 08:43

Die einzelnen Member dieses einfachen Structs werden am Ende selbst bei einem Move-Constructor kopiert. Anders lassen sich primitive Typen gar nicht transferieren. Und damit wird effektiv der Vektor (es handelt sich hier nicht um einen std::vector!) komplett kopiert. Das ganze Theater ist für Julién vermutlich auch komplett irrelevant. Wichtig ist, dass es geht.
Mich würde aber wundern, wenn hier ein Move stattfinden würde, solange es weder der Vektor, noch die Funktion implementiert. Blöder weise lässt sich ideone sich nicht überreden den Konstruktor nicht komplett zu inlinen und somit wird weder move, noch copy constructor aufgerufen.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »BlueCobold« (21.06.2015, 08:55)


9

21.06.2015, 19:45

Also, angeommen, du hast sowas hier:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
int Funktion(int a, int b)
{
 return a+b;
}

...

int Ergebnis=Funktion(5, 18-4);

Was semantisch passiert, ist ungefähr folgendes:
- Die Ausdrücke in den Parametern werden ausgewertet. Bei der 5 ist man schon fertig, bei dem 18-4 führt man erst die Rechnung durch, taucht eine Variable auf, wird deren Inhalt geladen.
- Nachdem alle Werte feststehen, werden sie in den Parameterspeicher für die Funktion kopiert.
- Die Funktion kann auf diesen Speicher zugreifen und mit den Werten tun, was sie will.
- Die Funktion errechnet ein Ergebnis. Die Return-Anweisung kopiert das Ergebnis in einen Ergebnis-Speicherplatz.
- Alle Speicherbereiche die die Funktion verwendet hat, werden freigegeben - mit Ausnahme des Ergebnis-Speicherplatzes.
- Der Funktionsaufruf ist beendet und der Aufrufer der Funktion kann auf den Ergebnis-Speicherplatz zugreifen.

Wenn man das genau so machen würde, würde man oft Werte hin und her kopieren, was unnötig langsam ist. Deshalb kann der Compiler optimierten Code generieren, was einfach bedeutet, dass der Code etwas anderes tut, aber immer das selbe Ergebnis dabei produziert. Es gibt dabei noch ein paar Regeln, was auf jeden Fall immer passieren muss, aber trotzdem hat der Compiler noch viele Freiheiten. Es ist zum Beispiel möglich, dass das Objekt, was am Ende zurückgegeben wird, überhaupt nicht im Speicher der Funktion erstellt wird, sondern direkt im Speicher des Aufrufes, so dass beim zurückkehren überhaupt nichts kopiert oder verschoben werden muss. Man will natürlich ein wenig darauf achten, dass man den Code so schreibt, dass der Compiler gute Möglichkeiten zum optimieren findet, aber im Grunde genommen, muss man sich keine Gedanken darüber machen, wie der Code genau funktioniert, so lange man weiß, welche Auswirkungen er genau hat.
Lieber dumm fragen, als dumm bleiben!

Julién

Alter Hase

  • »Julién« ist der Autor dieses Themas

Beiträge: 717

Wohnort: Bayreuth

Beruf: Student | Hilfswissenschaftler in der Robotik

  • Private Nachricht senden

10

21.06.2015, 20:56

Mit komplizierteren Worten:
Der Stackframe wird aufgeräumt, nachdem das Ergebnis kopiert worden ist?
I write my own game engines because if I'm going to live in buggy crappy filth, I want it to me my own - Ron Gilbert

Werbeanzeige