Gibt es Probleme mit der allokierung von Speicher innerhalb der Konstruktor-Initialisierung-Listen?
Benutzt habe ich die Initialisierung führt eine große Sache in meinem C++ - Programme, war aber nicht bewusst, dass man Speicher zuordnen.
So können Sie etwas tun (als ein erfundenes Beispiel) wie folgt:
class Test
{
private:
int* i;
int* j;
int count;
int* k;
public:
Test(void) : i(new int), j(new int[10]), count(10), k(new int[count])
{
}
~Test(void)
{
delete i;
delete [] j;
delete [] k;
}
};
Gibt es irgendwelche Probleme bei der Speicher-allocation in dieser Weise? Über die Reihenfolge der Initialisierung hier ist es sicher, ein parameter initialisiert, indem man die Initialisierung im gleichen Liste? also als ich reservieren count
bevor ich es verwenden, ist es sicher zu bedienen oder gibt es da eine spezielle Initialisierung, um die ich fallen könnte foul von?
InformationsquelleAutor der Frage Firedragon | 2012-01-30
Du musst angemeldet sein, um einen Kommentar abzugeben.
Es ist nicht exception-sicher. Wenn die
new
fürj
eine Ausnahme wirft, dann wird der Destruktor fürTest
ist nicht genannt, und so der Speicher füri
ist nicht freigegeben.Den Destruktor
i
wird aufgerufen, wenn die Initialisierung fürj
wirft, es ist nur so, dass ein raw-pointer hat keinen Destruktor. So könnte man es Ausnahme-sicher durch ersetzeni
mit einem geeigneten smart-pointer. In diesem Fallunique_ptr<int>
füri
undunique_ptr<int[]>
fürj
tun würde.Können Sie sich auf die Initialisierungen ausgeführt werden, in der richtigen Reihenfolge (die Reihenfolge der Elemente definiert sind, die nicht unbedingt der Reihenfolge in der Liste). Sie können sicher mit Daten-Mitglieder, die bereits initialisiert wurden, so gibt es kein problem mit der Verwendung von
count
bei der Initialisierung fürk
.InformationsquelleAutor der Antwort Steve Jessop
Dieser code kann ein Speicherleck in der Gegenwart ein Initialisierer, der eine Ausnahme auslöst.
Beachten Sie, dass dies gemacht werden könnte, um korrekt zu arbeiten, wenn die Mitglieder der
Test
wurden smart-eher als raw -- Zeiger.InformationsquelleAutor der Antwort NPE
Sind Sie allokierung von Speicher in Ihrem initialiser-Liste; dies ist völlig in Ordnung, aber Sie sind dann die Zuordnung der Zeiger auf diesen Speicher, um raw-Pointer.
Diese raw-Zeiger bedeutet nicht, dass jede Art von Speicher, das Eigentum oder die Löschung der Hinweise, die Sie zeigen, und als ein Ergebnis, der code enthält mehrere memory leaks, die nicht der "Rule of Five", und ist im Allgemeinen schlecht.
Eine weit bessere Art zu schreiben
Test
wäre:InformationsquelleAutor der Antwort Mankarse
Gibt es keine Probleme mit der Initialisierung -- Sie sind garantiert von der Norm zu tun ist, um, jedoch, denken Sie daran, dass, wenn alle diese Zuweisungen fehl, kann der ehemalige nicht befreit werden.
Also der einzige Nachteil ist, wollen Sie sicher zu halten gegen eine fehlgeschlagene Zuweisung -- dann würden Sie eher wollen, Sie zu initialisieren, um
nil
und im Konstruktor wickeln Sie die Zuordnung bis in einetry
block. Das ist in der Regel nicht erforderlich, obwohl, es sei denn, Ihre Anwendung ist in der realen Gefahr, die von der Speicher ausgeht, und muss wieder zu erholen.Natürlich gilt unter der Annahme, dass nur ein Mangel an Speicher kann eine exception werfen -- wenn Sie Objekte zuweisen, die werfen kann andere Ausnahmen, die Sie sollten mehr besorgt.
InformationsquelleAutor der Antwort Kornel Kisielewicz
Gibt es kein Problem mit dem Aufruf
new
aus der Initialisierungsliste.Jedoch, wenn Sie es für mehrere Mitglieder, es ist nicht exception-sicher, und Sie riskieren, Speicherverlust (was, wenn die erste
new
Aufruf erfolgreich, aber der zweite wirft eine exception? Dann wird die erste Zuweisung ist durchgesickert).Als für die Berufung auf die Initialisierung in Ordnung, das ist absolut sicher. Mitglieder sind initialisiert, in der Reihenfolge, in der Sie aufgeführt sind in der Klassendeklaration. So können Sie den Wert verwenden, der von Mitgliedern initialisiert früh initialisiert werden "später" Mitglieder.
Nur im Kopf behalten, dass es Ihr in der Reihenfolge der Deklaration innerhalb der Klasse, und nicht Ihrer Reihenfolge in der Initialisierungsliste bestimmt die Initialisierung bestellen. 🙂
InformationsquelleAutor der Antwort jalf
Angenommen, Sie haben:
Wenn die Initialisierung
p2
scheitert (entweder weilnew
wirft eine out-of-memory-Ausnahme oder weil dieT
Konstruktor fehlschlägt), dannp1
wird zugespielt werden. Um dies zu bekämpfen, C++ erlaubt die Verwendungtry
/catch
im Initialisierungs-Listen, aber es ist in der Regel ziemlich gross.InformationsquelleAutor der Antwort jamesdlin
Steve Jessop Antwort präsentiert Fallstricke.
Über die Bestellung, die ich denke, ist, was deine Frage behandelt:
Da in Ihrer Klasse
count
deklariert ist, bevork
du bist ok.InformationsquelleAutor der Antwort Luchian Grigore