360 Stimmen

Wann sollte ich das Schlüsselwort new in C++ verwenden?

Ich verwende C++ erst seit kurzem und habe mich über die new Stichwort. Sollte ich es einfach verwenden oder nicht?

  1. Mit dem new Stichwort...

    MyClass* myClass = new MyClass();
    myClass->MyField = "Hello world!";
  2. Ohne die new Stichwort...

    MyClass myClass;
    myClass.MyField = "Hello world!";

Aus der Perspektive der Implementierung scheinen sie sich nicht so sehr zu unterscheiden (aber ich bin sicher, dass sie es tun)... Allerdings ist meine primäre Sprache C#, und natürlich die erste Methode ist, was ich gewohnt bin.

Die Schwierigkeit scheint darin zu bestehen, dass Methode 1 mit den Standard-C++-Klassen schwieriger zu verwenden ist.

Welche Methode sollte ich anwenden?

Aktualisierung 1:

Ich habe vor kurzem die new Schlüsselwort für Haufen Speicher (oder freies Lager ) für ein großes Array, das den Anwendungsbereich verlässt (d.h. von einer Funktion zurückgegeben wird). Während ich zuvor den Stack verwendet hatte, was dazu führte, dass die Hälfte der Elemente außerhalb des Bereichs beschädigt wurde, konnte ich durch den Wechsel zur Heap-Nutzung sicherstellen, dass die Elemente intakt waren. Juhu!

Update 2:

Ein Freund von mir hat mir kürzlich erzählt, dass es eine einfache Regel für die Verwendung der new Schlüsselwort; jedes Mal, wenn Sie new , Typ delete .

    Foobar *foobar = new Foobar();
    delete foobar; // TODO: Move this to the right place.

Dies hilft, Speicherlecks zu vermeiden, da Sie das Löschen immer irgendwo unterbringen müssen (z. B. beim Ausschneiden und Einfügen in einen Destruktor oder anderweitig).

10voto

einpoklum Punkte 100527

C++ Core Guidelines R.11 : Vermeiden Sie die Verwendung von new et delete ausdrücklich.

Die Dinge haben sich erheblich verändert, seit die meisten Antworten auf diese Frage geschrieben wurden. Insbesondere hat sich C++ als Sprache weiterentwickelt, und die Standardbibliothek ist jetzt umfangreicher. Warum ist das wichtig? Wegen einer Kombination aus zwei Faktoren:

  • Verwendung von new et delete ist potenziell gefährlich: Der Speicher könnte auslaufen, wenn Sie nicht sehr diszipliniert mit delete alles, was Sie zugewiesen haben, zu löschen, wenn es nicht mehr gebraucht wird; und niemals delete was derzeit nicht zugewiesen ist.
  • Die Standardbibliothek bietet jetzt intelligente Zeiger die die new et delete aufruft, so dass Sie sich nicht selbst um die Verwaltung der Zuweisungen auf dem freien Speicher/Heap kümmern müssen. Das gilt auch für andere Container in der Standardbibliothek und anderswo.

Dies hat sich zu einer der "Kernrichtlinien" der C++-Gemeinschaft für das Schreiben von besserem C++-Code entwickelt, wie das verlinkte Dokument zeigt. Natürlich gibt es Ausnahmen von dieser Regel: Jemand muss die kapselnden Klassen schreiben, die Folgendes verwenden new et delete aber diese Person ist selten Sie selbst.

Ich schließe mich der gültigen Antwort von @DanielSchepler an:

3voto

Matt Davis Punkte 44077

Wenn Ihre Variable nur im Kontext einer einzigen Funktion verwendet wird, sollten Sie besser eine Stack-Variable verwenden, d. h. Option 2. Wie bereits gesagt wurde, müssen Sie die Lebensdauer von Stack-Variablen nicht verwalten - sie werden automatisch aufgebaut und zerstört. Außerdem ist das Allokieren/Deallokieren einer Variablen auf dem Heap vergleichsweise langsam. Wenn Ihre Funktion oft genug aufgerufen wird, werden Sie eine enorme Leistungssteigerung feststellen, wenn Sie Stack-Variablen gegenüber Heap-Variablen verwenden.

Allerdings gibt es einige offensichtliche Fälle, in denen Stack-Variablen unzureichend sind.

Wenn die Stack-Variable einen großen Speicherbedarf hat, besteht die Gefahr, dass der Stack überläuft. Standardmäßig, die Stapelgröße jedes Threads beträgt 1 MB unter Windows. Es ist unwahrscheinlich, dass Sie eine Stack-Variable mit einer Größe von 1 MB erstellen werden, aber Sie müssen bedenken, dass die Stack-Auslastung kumulativ ist. Wenn Ihre Funktion eine Funktion aufruft, die eine andere Funktion aufruft, die wiederum eine andere Funktion aufruft, die..., belegen die Stack-Variablen in all diesen Funktionen Platz auf demselben Stack. Bei rekursiven Funktionen kann dieses Problem schnell auftreten, je nachdem wie tief die Rekursion ist. Wenn dies ein Problem darstellt, können Sie die Größe des Stacks erhöhen (nicht empfohlen) oder die Variable mit dem new-Operator auf dem Heap zuweisen (empfohlen).

Die andere, wahrscheinlichere Bedingung ist, dass Ihre Variable über den Bereich Ihrer Funktion hinaus "leben" muss. In diesem Fall würden Sie die Variable auf dem Heap zuweisen, so dass sie außerhalb des Anwendungsbereichs einer bestimmten Funktion erreicht werden kann.

2voto

Timo Geusch Punkte 23597

Die einfache Antwort ist ja - new() erzeugt ein Objekt auf dem Heap (mit dem unglücklichen Nebeneffekt, dass man seine Lebensdauer verwalten muss (indem man explizit delete dafür aufruft), während die zweite Form ein Objekt im Stack im aktuellen Gültigkeitsbereich erzeugt und dieses Objekt zerstört wird, wenn es den Gültigkeitsbereich verlässt.

2voto

vartec Punkte 124396

Ohne die new Schlüsselwort, das Sie unter Aufrufstapel . Das Speichern von übermäßig großen Variablen auf dem Stack führt zu Stapelüberlauf .

1voto

itsmatt Punkte 30839

Übergeben Sie myClass aus einer Funktion heraus, oder erwarten Sie, dass es außerhalb dieser Funktion existiert? Wie einige andere schon sagten, geht es nur um den Anwendungsbereich, wenn Sie nicht auf dem Heap allozieren. Wenn Sie die Funktion verlassen, geht sie (irgendwann) weg. Einer der klassischen Fehler von Anfängern ist der Versuch, ein lokales Objekt einer Klasse in einer Funktion zu erstellen und es zurückzugeben, ohne es auf dem Heap zu allozieren. Ich erinnere mich noch gut daran, wie ich in meinen früheren Tagen mit C++ solche Dinge debuggen musste.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X