Ich sehe in C ++, dass es mehrere Möglichkeiten gibt, Daten zuzuweisen und freizugeben, und ich verstehe, dass Sie beim Aufrufen anrufen malloc
sollten free
und wenn Sie den new
Operator verwenden, mit dem Sie koppeln sollten, delete
und es ein Fehler ist, die beiden zu mischen (z. B. Aufrufen free()
von etwas, das erstellt wurde mit dem new
Operator), aber mir ist nicht klar, wann ich malloc
/ free
und wann ich new
/ delete
in meinen realen Programmen verwenden soll.
Wenn Sie ein C ++ - Experte sind, teilen Sie mir bitte die Faustregeln oder Konventionen mit, die Sie in dieser Hinsicht befolgen.
c++
memory-management
malloc
new-operator
JVApen
quelle
quelle
Antworten:
Wenn Sie nicht gezwungen sind, C zu verwenden, sollten Sie es niemals verwenden
malloc
. Immer benutzennew
.Wenn Sie einen großen Datenblock benötigen, gehen Sie einfach wie folgt vor:
Seien Sie vorsichtig, obwohl dies nicht korrekt ist:
Stattdessen sollten Sie dies tun, wenn Sie ein Datenarray löschen:
Das
new
Schlüsselwort ist die C ++ - Methode und stellt sicher, dass der Konstruktor Ihres Typs aufgerufen wird . Dasnew
Schlüsselwort ist außerdem typsicherer, währendmalloc
es überhaupt nicht typsicher ist.Ich könnte mir nur vorstellen, dass dies von Vorteil ist,
malloc
wenn Sie die Größe Ihres Datenpuffers ändern müssen . Dasnew
Schlüsselwort hat keine analoge Art wierealloc
. Dierealloc
Funktion kann möglicherweise die Größe eines Speicherblocks für Sie effizienter erweitern.Es ist erwähnenswert, dass Sie
new
/free
undmalloc
/ nicht mischen könnendelete
.Hinweis: Einige Antworten in dieser Frage sind ungültig.
quelle
new[]
viel sicherer alsstd::vector
? Wenn man verwendetnew[]
, würde der Zeiger nur über explizit ungültig werdendelete
, während der für a zugewiesene Speicherstd::vector
ungültig werden könnte, wenn die Größe des Vektors geändert wird oder der Gültigkeitsbereich verlassen wird. (Beachten Sie, dass bei Verwendungnew[]
die Möglichkeitdelete
berücksichtigt werden muss, dass möglicherweise nicht aufgerufen werden kann, wenn die asynchrone Methode noch aussteht. Wenn eine asynchrone Operation abgebrochen werden muss, muss möglicherweise das Löschen per Rückruf veranlasst werden.) .Die kurze Antwort lautet: Verwenden Sie
malloc
C ++ nicht ohne einen wirklich guten Grund dafür.malloc
hat eine Reihe von Mängeln bei der Verwendung mit C ++, dienew
definiert wurden, um zu überwinden.Durch C ++ - Code neu behobene Mängel
malloc
ist in keiner sinnvollen Weise typsicher. In C ++ müssen Sie die Rückgabe von umwandelnvoid*
. Dies führt möglicherweise zu vielen Problemen:Es ist schlimmer als das. Wenn es sich bei dem fraglichen Typ um POD (einfache alte Daten) handelt , können Sie
malloc
ihn wief2
im ersten Beispiel halbwegs sinnvoll verwenden , um Speicher zuzuweisen .Es ist jedoch nicht so offensichtlich, ob ein Typ POD ist. Die Tatsache, dass es für einen bestimmten Typ möglich ist, von POD zu Nicht-POD zu wechseln, ohne dass ein Compilerfehler auftritt und möglicherweise sehr schwer zu debuggen ist, ist ein wesentlicher Faktor. Wenn zum Beispiel jemand (möglicherweise ein anderer Programmierer) während der Wartung viel später eine Änderung vornehmen würde, die
foo
dazu führte , dass kein POD mehr vorhanden war, würde beim Kompilieren kein offensichtlicher Fehler auftreten, wie Sie hoffen würden, z.würde das machen
malloc
vonf2
auch schlecht werden , ohne offensichtliche Diagnose. Das Beispiel hier ist trivial, aber es ist möglich, versehentlich Nicht-PODness viel weiter entfernt einzuführen (z. B. in einer Basisklasse, indem ein Nicht-POD-Mitglied hinzugefügt wird). Wenn Sie C ++ 11 / Boost haben, können Sieis_pod
überprüfen, ob diese Annahme korrekt ist, und einen Fehler erzeugen, wenn dies nicht der Fall ist:Boost kann zwar nicht feststellen, ob ein Typ POD ohne C ++ 11 oder andere Compiler-Erweiterungen ist.
malloc
Gibt zurück,NULL
wenn die Zuordnung fehlschlägt.new
wird werfenstd::bad_alloc
. Das Verhalten der späteren Verwendung einesNULL
Zeigers ist undefiniert. Eine Ausnahme hat eine saubere Semantik, wenn sie ausgelöst wird und von der Fehlerquelle ausgelöst wird. Das Umschließenmalloc
mit einem geeigneten Test bei jedem Anruf erscheint mühsam und fehleranfällig. (Sie müssen nur einmal vergessen, um all diese gute Arbeit rückgängig zu machen). Eine Ausnahme kann sich auf eine Ebene ausbreiten, auf der ein Anrufer sie sinnvoll verarbeiten kann, wobeiNULL
es viel schwieriger ist, sie sinnvoll zurückzugeben. Wir könnten unseresafe_foo_malloc
Funktion erweitern, um eine Ausnahme auszulösen oder das Programm zu beenden oder einen Handler aufzurufen:Grundsätzlich
malloc
handelt es sich um eine C-Funktion undnew
eine C ++ - Funktion. Infolgedessenmalloc
spielt es mit Konstruktoren nicht gut, sondern es wird nur ein Teil der Bytes zugewiesen. Wir könnten unseresafe_foo_malloc
Platzierung weiter ausbauen , um die Platzierung zu nutzennew
:Unsere
safe_foo_malloc
Funktion ist nicht sehr allgemein gehalten - im Idealfall möchten wir etwas, das für jeden Typ geeignet ist, nicht nurfoo
. Dies können wir mit Vorlagen und variadischen Vorlagen für nicht standardmäßige Konstruktoren erreichen:Bei der Behebung aller bisher identifizierten Probleme haben wir den Standardoperator praktisch neu erfunden
new
. Wenn Sie verwendenmalloc
und platzieren möchten, könnennew
Sie es auch gleich verwendennew
!quelle
struct
und imclass
Grunde dasselbe bedeutet. Ich frage mich, ob es Probleme gegebenstruct
hätte, für PODs reserviert zu sein und möglicherweise davon auszugehen, dass alleclass
Typen Nicht-PODs sind. Alle durch Code definierten Typen, die vor der Erfindung von C ++ definiert wurden, wären notwendigerweise PODs, daher würde ich nicht denken, dass die Abwärtskompatibilität dort ein Problem darstellen würde. Gibt es Vorteile nicht-PODs Typen mit deklarierten alsstruct
stattclass
?struct
und zuclass
tun, die jetzt eine nette Funktion namens "Metaclasses" (von Herb) ermöglicht .$class
. Ich bin mir jedoch nicht sicher, was das damit zu tun hatclass
und wasstruct
Synonyme sind.class
undstruct
effektiv bedeuten, können Sie beliebige Transformationen an ihnen durchführen ($class
), ohne sich Gedanken über einclass
a machen zu müssenstruct
und umgekehrt.Aus dem C ++ FQA Lite :
Entschuldigung, ich konnte einfach nicht widerstehen. :) :)
quelle
Verwenden Sie in C ++ immer new. Wenn Sie einen Block untypisierten Speichers benötigen, können Sie den Operator new direkt verwenden:
quelle
operator new
istoperator delete
. Es ist keine genau definierte Aktion,delete
einen Ausdruck mit Typ aufzurufenvoid*
.Verwendung
malloc
und nur zum Zuweisen von Speicher, der von c-zentrierten Bibliotheken und APIs verwaltet werden soll. Verwenden Sie und (und die Varianten) für alles, was Sie steuern.free
new
delete
[]
quelle
malloc
. Wenn eine Funktion wiestrdup
ein Objekt erstellen und an einen Aufrufer zurückgeben muss, ist es durchaus sinnvoll anzugeben, dass der Aufruferfree
das Objekt aufrufen muss, wenn es nicht mehr benötigt wird. Wie könnten solche Funktionen vermeiden, dass sie dem Anrufer ihre Verwendung von malloc / free aussetzen?malloc
in C ++?neu gegen malloc ()
1)
new
ist ein Operator , währendmalloc()
es sich um eine Funktion handelt .2)
new
ruft Konstruktoren auf , währendmalloc()
dies nicht der Fall ist.3)
new
liefert genauen Datentyp , währendmalloc()
kehrt void * .4) gibt
new
niemals NULL zurück (wird bei einem Fehlermalloc()
ausgelöst ), während NULL zurückgegeben wird5) Neuzuweisung von Speicher, der nicht von
new
whilemalloc()
can verarbeitet wirdquelle
char* ptr = new (std::nothrow) char [323232];
new
Funktionrealloc
anstattmalloc
, und mit dem Zeigervariable beginnen initialisiertNULL
. Wenn Sie andererseits einen veränderbaren Speicherblock in C ++ möchten , würde ich vorschlagen,std::vector
im Gegensatz zurealloc
... dem oder einer Datei.Um Ihre Frage zu beantworten, sollten Sie den Unterschied zwischen
malloc
und kennennew
. Der Unterschied ist einfach:malloc
weist Speicher zu , währendnew
Speicher zuweist UND den Konstruktor des Objekts aufruft, für das Sie Speicher zuweisen .Wenn Sie also nicht auf C beschränkt sind, sollten Sie malloc niemals verwenden, insbesondere wenn Sie mit C ++ - Objekten arbeiten. Das wäre ein Rezept, um Ihr Programm zu brechen.
Auch der Unterschied zwischen
free
unddelete
ist ziemlich gleich. Der Unterschied besteht darin, dassdelete
zusätzlich zur Speicherfreigabe der Destruktor Ihres Objekts aufgerufen wird.quelle
Es gibt einen großen Unterschied zwischen
malloc
undnew
.malloc
ordnet Speicher zu. Dies ist für C in Ordnung, da in C ein Speicherklumpen ein Objekt ist.Wenn Sie in C ++ nicht mit POD-Typen (die C-Typen ähnlich sind) arbeiten, müssen Sie einen Konstruktor an einem Speicherort aufrufen, um tatsächlich ein Objekt dort zu haben. Nicht-POD-Typen sind in C ++ sehr verbreitet, da viele C ++ - Funktionen ein Objekt automatisch zu einem Nicht-POD machen.
new
weist Speicher zu und erstellt ein Objekt an diesem Speicherort. Für Nicht-POD-Typen bedeutet dies, einen Konstruktor aufzurufen.Wenn Sie so etwas tun:
Der Zeiger, den Sie erhalten, kann nicht dereferenziert werden, da er nicht auf ein Objekt zeigt. Sie müssen einen Konstruktor darauf aufrufen, bevor Sie ihn verwenden können (und dies erfolgt mithilfe der Platzierung
new
).Wenn Sie andererseits Folgendes tun:
Sie erhalten einen Zeiger, der immer gültig ist, weil
new
ein Objekt erstellt wurde.Selbst für POD-Typen gibt es einen signifikanten Unterschied zwischen den beiden:
Dieser Code würde einen nicht angegebenen Wert ausgeben, da die von erstellten POD-Objekte
malloc
nicht initialisiert werden.Mit
new
können Sie einen Konstruktor angeben, der aufgerufen werden soll, und so einen genau definierten Wert erhalten.Wenn Sie es wirklich wollen, können Sie es verwenden
new
, um nicht initialisierte POD-Objekte zu erhalten. Weitere Informationen hierzu finden Sie in dieser anderen Antwort .Ein weiterer Unterschied ist das Verhalten bei einem Ausfall. Wenn kein Speicher zugewiesen werden kann, wird
malloc
ein Nullzeiger zurückgegeben, währendnew
eine Ausnahme ausgelöst wird.Ersteres erfordert, dass Sie jeden zurückgegebenen Zeiger testen, bevor Sie ihn verwenden, während letzteres immer gültige Zeiger erzeugt.
Aus diesen Gründen sollten Sie in C ++ - Code verwenden
new
und nichtmalloc
. Aber selbst dann sollten Sie nichtnew
"im Freien" verwenden, da es Ressourcen beschafft, die Sie später freigeben müssen. Wenn Sie verwendennew
, sollten Sie das Ergebnis sofort an eine Ressourcenverwaltungsklasse übergeben:quelle
Eine dynamische Zuordnung ist nur erforderlich, wenn die Lebensdauer des Objekts von dem Bereich abweichen soll, in dem es erstellt wird (dies gilt auch, um den Bereich kleiner als größer zu machen) und Sie einen bestimmten Grund haben, warum das Speichern nach Wert dies nicht tut Arbeit.
Zum Beispiel:
Ab C ++ 11 müssen wir uns
std::unique_ptr
mit dem zugewiesenen Speicher befassen, der den Besitz des zugewiesenen Speichers enthält.std::shared_ptr
wurde erstellt, wenn Sie das Eigentum teilen müssen. (Sie benötigen dies weniger als Sie in einem guten Programm erwarten würden)Das Erstellen einer Instanz wird ganz einfach:
C ++ 17 fügt außerdem hinzu,
std::optional
wodurch verhindert werden kann, dass Speicherzuordnungen erforderlich sindSobald 'Instanz' den Gültigkeitsbereich verlässt, wird der Speicher bereinigt. Die Übertragung des Eigentums ist auch einfach:
Wann brauchen Sie noch
new
? Fast nie ab C ++ 11. Die meisten davon verwenden Sie,std::make_unique
bis Sie zu einem Punkt gelangen, an dem Sie auf eine API stoßen, die den Besitz über Rohzeiger überträgt.In C ++ 98/03 müssen Sie die manuelle Speicherverwaltung durchführen. In diesem Fall versuchen Sie, ein Upgrade auf eine neuere Version des Standards durchzuführen. Wenn Sie nicht weiterkommen:
Stellen Sie sicher, dass Sie den Besitz korrekt verfolgen, um keine Speicherlecks zu haben! Die Bewegungssemantik funktioniert auch noch nicht.
Wann brauchen wir Malloc in C ++? Der einzig gültige Grund wäre, Speicher zuzuweisen und ihn später durch Platzierung neu zu initialisieren.
Obwohl das oben Gesagte gültig ist, kann dies auch über einen neuen Operator erfolgen.
std::vector
ist ein gutes Beispiel dafür.Endlich haben wir noch den Elefanten im Raum :
C
. Wenn Sie mit einer C-Bibliothek arbeiten müssen, in der Speicher im C ++ - Code zugewiesen und im C-Code freigegeben wird (oder umgekehrt), müssen Sie malloc / free verwenden.Wenn Sie in diesem Fall sind, vergessen Sie virtuelle Funktionen, Elementfunktionen, Klassen ... Nur Strukturen mit PODs sind zulässig.
Einige Ausnahmen von den Regeln:
quelle
Es gibt ein paar Dinge, die
new
dasmalloc
nicht tun:new
Konstruiert das Objekt durch Aufrufen des Konstruktors dieses Objektsnew
erfordert keine Typumwandlung des zugewiesenen Speichers.Wenn Sie also verwenden
malloc
, müssen Sie die oben genannten Dinge explizit ausführen, was nicht immer praktisch ist. Darüber hinausnew
kann überlastet werden,malloc
kann aber nicht sein.quelle
Wenn Sie mit Daten arbeiten, die nicht erstellt / zerstört werden müssen und eine Neuzuweisung erfordern (z. B. eine große Anzahl von Ints), ist malloc / free meiner Meinung nach eine gute Wahl, da Sie eine Neuzuweisung erhalten, die viel schneller ist als new-memcpy -delete (es ist auf meiner Linux-Box, aber ich denke, dies kann plattformabhängig sein). Wenn Sie mit C ++ - Objekten arbeiten, die kein POD sind und eine Konstruktion / Zerstörung erfordern, müssen Sie die Operatoren new und delete verwenden.
Wie auch immer, ich verstehe nicht, warum Sie nicht beide verwenden sollten (vorausgesetzt, Sie geben Ihren Speicher frei und löschen mit neu zugewiesene Objekte), wenn Sie den Geschwindigkeitsschub nutzen können (manchmal einen signifikanten, wenn Sie große Arrays neu zuweisen von POD), die Realloc Ihnen geben kann.
Sofern Sie es nicht benötigen, sollten Sie sich in C ++ an new / delete halten.
quelle
Wenn Sie C-Code haben, den Sie nach C ++ portieren möchten, können Sie alle malloc () -Aufrufe darin belassen. Für jeden neuen C ++ - Code würde ich empfehlen, stattdessen new zu verwenden.
quelle
Wenn Sie C ++ verwenden, versuchen Sie, new / delete anstelle von malloc / calloc zu verwenden, da es sich um Operatoren handelt. Für malloc / calloc müssen Sie einen weiteren Header einfügen. Mischen Sie nicht zwei verschiedene Sprachen im selben Code. Ihre Arbeit ist in jeder Hinsicht ähnlich, beide ordnen Speicher dynamisch aus dem Heap-Segment in der Hash-Tabelle zu.
quelle
new
initialisiert die Standardwerte der Struktur und verknüpft die darin enthaltenen Referenzen korrekt mit sich selbst.Z.B
Es
new struct test_s
wird also eine initialisierte Struktur mit einer Arbeitsreferenz zurückgegeben, während die malloc'ed-Version keine Standardwerte hat und die internen Referenzen nicht initialisiert sind.quelle
Aus einer niedrigeren Perspektive initialisiert new den gesamten Speicher, bevor der Speicher übergeben wird, während malloc den ursprünglichen Inhalt des Speichers beibehält.
quelle
Im folgenden Szenario können wir new nicht verwenden, da es den Konstruktor aufruft.
quelle
Die
new
unddelete
Betreiber können auf Klassen arbeiten und Strukturen, währendmalloc
undfree
nur Arbeit mit Blöcken des Speichers, muß gegossen werden.Die Verwendung
new/delete
hilft dabei, Ihren Code zu verbessern, da Sie den zugewiesenen Speicher nicht in die erforderliche Datenstruktur umwandeln müssen.quelle
In seltenen Fällen sollten Sie die Verwendung von malloc / free anstelle von new / delete in Betracht ziehen, wenn Sie mit realloc zuweisen und dann neu zuweisen (einfache Pod-Typen, keine Objekte), da es in C ++ keine ähnliche Funktion wie realloc gibt (obwohl dies mit a möglich ist mehr C ++ Ansatz).
quelle
malloc () wird verwendet, um Speicher in C dynamisch zuzuweisen, während new () in c ++ dieselbe Arbeit erledigt. Sie können also keine Codierungskonventionen von 2 Sprachen mischen. Es wäre gut, wenn Sie nach dem Unterschied zwischen calloc und malloc fragen würden ()
quelle
malloc
in C ++ verwenden.