C ++ Objekt ohne neu

77

Dies ist eine wirklich einfache Frage, aber ich habe C ++ jahrelang nicht richtig gemacht und bin daher ein wenig verblüfft. Außerdem ist es (zumindest für mich) nicht die einfachste Sache, im Internet nachzuschlagen, nicht es zu versuchen.

Warum wird das newSchlüsselwort nicht verwendet und wie funktioniert es?

Was ist hier im Grunde los?

CPlayer newPlayer = CPlayer(position, attacker);
Henry B.
quelle

Antworten:

65

Dieser Ausdruck:

CPlayer(position, attacker)

Erstellt ein temporäres Objekt vom Typ CPlayermit dem obigen Konstruktor. Dann:

CPlayer newPlayer =...;

Das erwähnte temporäre Objekt wird mit dem Kopierkonstruktor nach kopiert newPlayer. Ein besserer Weg ist, Folgendes zu schreiben, um Zeiträume zu vermeiden:

CPlayer newPlayer(position, attacker);
AraK
quelle
7
Eigentlich wird der Compiler es wahrscheinlich optimieren. In diesem Fall wird der Kopierkonstruktor nicht aufgerufen. stackoverflow.com/questions/1758142/…
BostonLogan
5
Eine Zuweisung in einer Deklaration ist nicht weniger effizient als die Verwendung der Konstruktorsyntax. Wenn sie getrennte Aussagen gewesen wären, wäre die Bemerkung über Provisorien richtig. Das Wesentliche ist, dass dies einen CPlayer deklariert (normalerweise auf dem Stapel), anstatt ihm Speicherplatz aus dem freien Speicher (Heap) zuzuweisen.
Adrian McCarthy
1
Nein, fast per Definition: Objekte auf dem Stapel leben nur, während sie sich im Gültigkeitsbereich befinden. stackoverflow.com/search?q=%5Bc%2B%2B%5D+stack+heap
Josh Lee
1
Ich denke nicht, dass diese Antwort genau richtig ist. Der Code des OP sieht so aus, als würde er temporär erstellt und dann kopiert, aber der Standard 12.1.11 schlägt etwas anderes vor. Es ist nur ein normaler Konstruktoraufruf, den Jleedev entdeckt hat.
Michael Kristofik
9
Es ist Sache des Compilers, Kopien zu entfernen oder nicht (in Situationen, in denen dies zulässig ist). 12.8 / 15.
Steve Jessop
55

Das obige erstellt ein CPlayer-Objekt auf dem Stapel, daher wird es nicht benötigt new. Sie müssen nur verwenden, newwenn Sie versuchen, ein CPlayer-Objekt auf dem Heap zuzuweisen. Wenn Sie die Heap-Zuordnung verwenden, sieht der Code folgendermaßen aus:

CPlayer *newPlayer = new CPlayer(position, attacker);

Beachten Sie, dass wir in diesem Fall einen Zeiger auf ein CPlayer-Objekt verwenden, das durch einen übereinstimmenden Aufruf von bereinigt werden muss delete. Ein auf dem Stapel zugewiesenes Objekt wird automatisch zerstört, wenn es den Gültigkeitsbereich verlässt.

Eigentlich wäre es einfacher und offensichtlicher gewesen zu schreiben:

CPlayer newPlayer(position, attacker);

Viele Compiler optimieren ohnehin die Version, die Sie oben gepostet haben, und es ist klarer zu lesen.

Timo Geusch
quelle
2
Ich denke nicht, dass dies richtig ist: "Ein auf dem Heap zugewiesenes Objekt wird automatisch zerstört, wenn es den Gültigkeitsbereich verlässt."
Valentin
1
Sie haben Recht, ich wollte "Stapel" schreiben, nicht "Haufen". Vielen Dank für den Hinweis.
Timo Geusch
Stimmen Sie dem zu. Wir sollten den C ++ - Code im gleichen Stil wie den C-Code halten. Es CPlayer newPlayer(position, attacker);ist also besser, als CPlayer newPlayer = CPlayer(position, attacker);wenn Sie eine Stapelvariable erstellen möchten.
Tonga
10
CPlayer newPlayer = CPlayer(position, attacker);

Diese Zeile erstellt ein neues lokales Objekt vom Typ CPlayer. Trotz seines funktionsähnlichen Erscheinungsbilds wird der Konstruktor von CPlayer einfach aufgerufen. Es sind keine Provisorien oder Kopierungen erforderlich. Das Objekt mit dem Namen newPlayer lebt so lange wie der Bereich, in dem es eingeschlossen ist. Sie verwenden das newSchlüsselwort hier nicht, da C ++ nicht Java ist.

CPlayer* newPlayer = new CPlayer(position, attacker);

Diese Zeile erstellt ein CPlayer-Objekt auf dem Heap und definiert einen Zeiger namens newPlayer, der darauf zeigt. Das Objekt lebt, bis es jemand deleteist.

Michael Kristofik
quelle
3
"Es sind keine Provisorien oder Kopierungen erforderlich" - Dies ist nicht genau richtig. Es gibt keine solche Garantie. Aber jeder anständige Compiler sollte die Kopie weglassen.
Sellibitze
6

newPlayer ist keine dynamisch zugewiesene Variable, sondern eine automatisch stapelzugeordnete Variable:

CPlayer* newPlayer = new CPlayer(pos, attacker);

unterscheidet sich von

CPlayer newPlayer = CPlayer(pos, attacker);

newPlayer wird auf dem Stapel über den normalen Aufruf des CPlayer-Konstruktors (Position, Angreifer) zugewiesen, wenn auch etwas ausführlich als üblich

CPlayer newPlayer(pos, attacker);

Es ist im Grunde das gleiche wie zu sagen:

int i = int(3);
Digitalarbeiter
quelle
2
Vorsicht hier. Es ist eine "Kopierinitialisierung". Es ist keine Aufgabe.
Sellibitze
Ich stehe korrigiert da, es ist keine Aufgabe; Auch der Kopierkonstruktor ist nicht beteiligt. Antwort entsprechend bearbeiten.
Digitalarbeiter
2
Sicher, der Kopierer ist (zumindest logisch) involviert. Sie werden das bemerken, wenn Sie Ihre Kopie privat machen. Dann funktioniert diese Kopierinitialisierung nicht mehr. Der C ++ - Standard erfordert einen zugänglichen Kopiercode, auch wenn der Compiler die Kopie optimieren kann.
Sellibitze
Nein, neue Zuweisungen auf dem Haufen, Ihr zweiter Spieler ist auf dem Stapel gedacht