2010-08-12 10 views
6

Welcher ist der richtige Weg, um Speicher über new im C++ - Konstruktor zuzuweisen. Erste Art und Weise in der Argumentliste:Was ist der richtige Weg, um Speicher im C++ - Konstruktor zuzuordnen?

class Boda { 
    int *memory; 
    public: 
     Boda(int length) : memory(new int [length]) {} 
     ~Boda() { delete [] memory; } 
}; 

oder im Körper des Konstruktor:

class Boda { 
    int *memory; 
    public: 
     Boda(int length) { 
      memory = new int [length]; 
     } 
     ~Boda() { delete [] memory; } 
}; 

Danke, Boda cyclo.

+6

Ich weiß, das ist nur Beispielcode, aber wie geschrieben, hat die Klasse schwerwiegende Speicherverwaltungsprobleme (die Standard-Kopie ctor wird ermöglichen, Speicher mehrfach freigegeben zu werden). Verwenden Sie RAII, verwenden Sie intelligente Zeiger oder Container. mit der richtigen RAII können Sie finden, dass Sie nicht brauchen, um sich überhaupt zu löschen –

+8

@jk: Abgesondert würde ich eine 'std :: vector ' bevorzugen. – fredoverflow

Antwort

3

Ich denke, der einfachste Weg, dies zu tun wäre, eine boost scoped array verwenden und lassen Sie jemand anderen gut getestet Bibliothekscode alles für Sie.

So:

class Boda { 
    boost::scoped_array<int> memory; 
    public: 
     Boda(int length) : memory(new int [length]) {} 
     ~Boda() {} 
}; 

Außerdem scoped Arrays können nicht kopiert werden - so vermeiden Sie die fiese Copykonstruktor Deallokation Problem in einer anderen Antwort erwähnt.

+0

Eigentlich sollten Sie 'boost :: scoped_array' verwenden. –

+0

Danke. Gerade entdeckt, es war ein Array Alloc. Bringen Sie mir bei, die Frage richtig zu lesen. –

+1

'delete' ist ein Code-Geruch: Er sollte nur in dedizierten Ressourcen-Management-Klassen erscheinen ... und diese sind oft bereits in verfügbaren Bibliotheken richtig codiert (zB STL/Boost). –

-1

Wenn Sie Speicherzuordnungsfehler abfangen möchten (was Sie wahrscheinlich tun sollten), müssen Sie den Aufruf von new im Rumpf des Konstruktors vornehmen.

+12

Nicht wahr, eigentlich. (Und in beiden Fällen. Wenn die Speicherzuweisung fehlschlägt, kann dieser Konstruktor nichts dagegen tun und sollte daher die Ausnahme nicht abfangen. Und Sie können eine Funktion try block verwenden, um das Ganze in einen try-catch-Block zu bekommen .) – GManNickG

1

Ich würde sagen, beide sind gleichwertig in der Wirkung, die sie produzieren und beide sind "der richtige Weg". Ich bevorzuge Initialisierungslisten, aber ich würde mit der zweiten Variante gehen, nur in der Lage sein, auf ungültige Länge Argument zu testen, bevor Sie versuchen, den Speicher zuzuordnen.

+1

Sie sind gleichwertig für einfache Typen, aber im Allgemeinen sind sie nicht. Wenn Sie die Initialisiererliste verwenden, wird das Objekt aus den Argumenten erstellt. Wenn Sie den Konstruktor-Body verwenden, wird das Objekt standardmäßig konstruiert und dann neu zugewiesen. Dies ist möglicherweise weniger effizient und funktioniert nur, wenn das Objekt standardmäßig konstruierbar und zuweisbar ist. –

2

Sie sollten Ressourcenverwaltungsklassen verwenden, die dies für Sie erledigen. Sonst gibt es einige ernsthafte Probleme mit der Ausnahmesicherheit, abgesehen von unnötiger Duplizierung bestehender Logik und Wartung von Kopier-/Zuweisungsoperatoren.

0

memory Membervariable ist ein Zeiger, wenn Sie es in Initialisierungsliste zuteilen und es fehlschlägt, Ihre Klasse nicht initialisiert und Sie brauchen es nicht zu befreien später (dank RAH-Entwurfsmuster, das durch C verwendet wird ++ zur Klasseninitialisierung). Wenn Sie seinen Speicher im Körper des Konstruktors zuweisen, wird ähnliches Verhalten auftreten.

Aber wenn Sie etwas behandeln wollen, dann ordnen Sie seinen Speicher im Körper des Konstruktors. Überprüfen Sie etwas oder versuchen Sie, es abzufangen oder einige nützliche Nachrichten auszudrucken, aber Sie müssen zumindest eine weitere Ausnahme auslösen, da Ihre Klasseninitialisierung fehlerhaft ist.

Ich denke, memory Zuordnung im Körper des Konstruktors ist lesbarer als die andere.

Verwandte Themen