2013-06-27 11 views
8

Ich schreibe eine Template-Klasse, die intern ein Array des angegebenen Typs verwaltet. Wie folgt aus:Löscht [] Aufrufdestruktoren?

template<typename T> 
class Example { 
    // ... 
private: 
    T* objects; // allocated in c'tor (array), deleted in d'tor 
    // ... 
}; 

Ich frage mich, ob C++ ruft die destructor jedes Objekts in objects, wenn ich es über delete[] objects; löschen.

Ich muss das wissen, weil die Objekte in meiner Klasse die ganze Zeit keine vernünftigen Werte enthalten, so dass die Destruktoren nicht aufgerufen werden sollten, wenn sie es nicht tun.

Außerdem würde ich gerne wissen, ob die Destruktoren aufgerufen würden, wenn ich ein Array fester Größe wie T objects[100] als Teil von Example<T> deklariert.

+14

"weil die Objekte in meiner Klasse die ganze Zeit keine vernünftigen Werte enthalten" Diese Klasse klingt gebrochen. –

+0

Die Klasse ist eine Sammlung, die Speicherplatz im Voraus reserviert, den sie nicht immer verwendet. Ich muss diesen Raum nicht mit NULLs füllen, weil die Klasse bereits weiß, welche Elemente verwendet werden und welche nicht. – Mixthos

+0

Wenn 'new []' Konstruktoren aufruft, ist es nur logisch für 'delete []' Destruktoren aufzurufen. Es ist nur logisch. – dtech

Antwort

18

Wenn T einen Destruktor hat, wird es von delete[] aufgerufen. Abschnitt Von 5.3.5 Löschen des C++ 11-Standard (Entwurf n3337), Ziffer 6:

Wenn der Wert des Operanden des Löschausdruckes ist kein Null-Zeiger-Wert, der Lösch -expression wird den Destruktor aufrufen (falls vorhanden), damit das Objekt oder die Elemente des Arrays gelöscht werden. Im Falle eines Arrays werden die Elemente in der Reihenfolge der abnehmenden Adresse zerstört (dh in umgekehrter Reihenfolge der Fertigstellung ihres Konstruktors ; siehe 12.6.2).

Der Destruktor für einen Typen T wird auch für jedes Element in einer Anordnung von T[] aufgerufen werden, wenn die Anordnung nicht dynamisch zugewiesen ist und Array-geht (Enden Lebensdauer) außerhalb des Gültigkeitsbereiches.


Ich muss das wissen, weil die Objekte in meiner Klasse nicht sinnvolle Werte die ganze Zeit enthalten, so sollten die Destruktoren nicht aufgerufen werden, wenn sie es nicht tun.

Aber es scheint ein sehr signifikantes Problem mit einem Objekt zu sein, die einen Zustand erwerben können, wo sie nicht zerstört werden kann.

1

delete[] objects ist ähnlich (aber nicht identisch) zu:

for (i = 0; i < num_of_objects; ++i) { 
    delete objects[i]; 
} 

seit delete ruft den destructor, können Sie delete[] erwarten das Gleiche zu tun.

3

Ja, der Destruktor wird für alle Objekte im Array aufgerufen, wenn delete[] verwendet wird. Aber das sollte kein Problem sein, da der Konstruktor für alle Objekte im Array aufgerufen wurde, wenn Sie new[] (Sie haben, oder?), Um es zuzuordnen.

Wenn ein konstruiertes Objekt in einem solchen Zustand sein kann, dass der Aufruf des Destruktors ungültig wäre, dann liegt etwas ernsthaft falsch an Ihrem Objekt vor. Sie müssen Ihren Destruktor in allen Fällen arbeiten lassen.

1

delete [] ruft den Destruktor für jedes Element des Arrays auf. Gleiches passiert für ein Element-Array (Ihre T objects[100]).

Sie wollen es als Zeiger zu halten, und Design den destructor (und Konstruktor kopieren und kopieren Zuweisungsoperator finden rule of three/five) für die Vorlage mit „nicht-sensible“ Werten zu behandeln, die von objects hingewiesen.

2

Die Antwort ist ja. Destruktor für jedes Objekt wird aufgerufen.

In einem verwandten Hinweis sollten Sie versuchen, die Verwendung von delete wann immer möglich zu vermeiden. Verwenden Sie stattdessen Smartpointer (z. B. unique_ptr, shared_ptr) und STL-Container (z. B. std :: vector, std :: array).

0

Ja, delete[] garantiert, dass Destruktoren für jedes Objekt aufgerufen werden.

Abhängig von Ihrem Anwendungsfall kann die Verwendung von Boost pointer containers oder einfach Containern von Smartpointern die Sammlung von Zeigern (ausnahmesicher) wesentlich erleichtern.