2009-11-23 11 views
5
class MyClass 
{ 
}; 

void foo 
{ 
    MyClass arr[10]; 
} 

Ich möchte die Reihenfolge der Zerstörung von Array-Objekten wissen, wenn die Funktion zurückkehrt.Reihenfolge der Zerstörung für Array von Objekten

Ich las es effektiver, C++ darüber und es sagt, dass destructor in umgekehrter Reihenfolge, die der Konstruktor, um wie folgt aufgerufen werden:

for(int i = 9 ; i >= 0 ;i--) 
{ 
    arr[i].MyClass::~MyClass(); 
} 

Kann jemand mir sagen, der Grund dafür?

Antwort

2

Die von destructor Invokation Filosophie von C++ Fortsetzung der umgekehrten Reihenfolge ist. Wenn gestapelte Objekte zerstört werden, geschieht dies in umgekehrter Reihenfolge, um RAII zu erleichtern. Obwohl das für Array-Elemente nicht wirklich notwendig ist (sie sind alle mit den Standardkonstruktoren konstruiert und jede Reihenfolge von Konstruktion/Zerstörung würde genügen), wird das gleiche mit ihnen getan, nur aus Gründen der Konsistenz.

+1

Sie sind alle mit den Standardkonstruktoren konstruiert und jede Reihenfolge der Konstruktion/Destruktion würde tun. "Da ein No-Arg-Konstruktor auf Globals zugreifen kann (zB Klassenstatik), macht es für das resultierende Array einen Unterschied, in welcher Reihenfolge sie stehen." Ich bin nicht ganz sicher, was Sie mit "jeder Auftrag würde tun" bedeuten - nur eine Bestellung entspricht 12.6 des Standards. Der Standard könnte gesagt haben, dass die Reihenfolge implementation-defined war, oder hätte sagen können, dass sie konstruiert sind in umgekehrter Reihenfolge der Anzahl der unterschiedlichen Primfaktoren im Index, wobei die Bindungen durch die Ziffernsumme in der Basis 7 bestimmt werden ;-) –

0

Vielleicht in dem die Reihenfolge der Objekte, die das Array bilden, sind auf dem Stapel abgelegt. Wie auch immer, außer Neugierde kann ich mir keinen Grund vorstellen, sich um den Zerstörungsbefehl zu sorgen.

+0

Wenn sich arr [n] in seinem DTor auf Element arr [n + 1] bezieht, kann es zu Problemen kommen Englisch: emagazine.credit-suisse.com/app/art ... = 157 & lang = en Ich denke jedoch nicht an eine Situation in der realen Welt, in der das nötig sein könnte: – foraidt

+0

@mxp: Ganz einverstanden, aber wenn jedes Element eines Arrays zumindest davon abhängt Eines der Elemente des Arrays, die Reihenfolge der Zerstörung der Elemente des Arrays wird nur ein kleines Problem sein. – jrbjazz

2

Die Informationen, die Sie sich beziehen sind in effektiver C++ auf Objekte angewendet wird, die ein paar anderen Objekt enthalten, wie in diesem Fall:

class Foo { 
    private: 
    Bar bar_1; 
    Bar bar_2; 

    public: 
    Foo() : bar_1(), bar_2() {} 
}; 

Im obigen Beispiel, haben Sie bar_1 zuerst konstruiert , gefolgt von bar_2. Wenn ein Objekt der Klasse Foo dann zerstört wird, wird bar_2 zuerst zerstört, dann bar_1. Darauf bezieht sich Scott Meyers.

Aus der Sicht der Klasse wäre ein Array von Balken ein anderes Objekt, das der Compiler zerstören muss, so dass die Reihenfolge der Zerstörung beeinflusst wird, wenn das Array im Kontext der anderen Objekte in der Klasse zerstört wird.

Wie zu welcher Reihenfolge die Elemente eines Arrays zerstört werden, würde ich nicht zu wundern, wenn die Umsetzung abhängig ist. Hier spielt auch die Optimierung eine Rolle (zum Beispiel kann ein POD-Array einfach dadurch zerstört werden, dass es seinen Speicher freigibt, wie es ein Objekt sein kann, das ausschließlich aus PODs besteht). All dies kann die Reihenfolge beeinflussen, in der die Elemente eines Arrays zerstört werden.

würde ich interessieren zu sehen, warum Sie den Auftrag tun müssen wissen, in dem die Array-Elemente zerstört werden (abgesehen von technischen Neugier, das ein triftiger Grund IMHO wäre). Wenn zwischen den Elementen des Arrays Abhängigkeiten bestehen, muss die Datenstruktur möglicherweise überprüft werden.

1

Jede Bestellung würde wirklich tun. Die zwei offensichtlichen Wahlmöglichkeiten sind natürlich in der Reihenfolge oder in umgekehrter Reihenfolge. In diesem Fall dachte jedoch keiner der Compiler-Hersteller, dass es sich lohnen würde, diese Implementierung abhängig zu machen. Daher wurde die Wahl getroffen, um die umgekehrte Reihenfolge zu verlangen (wie scharf angegeben, Erweiterung der üblichen LIFO-Verhalten)

0

Sie zitieren nicht, welche Seite in Meyer's Buch Sie beziehen, aber ich stimme mit Timo Geusch, dass die Erklärung klingt wie es sich bezieht, dass Konstruktoren und Destruktoren entsprechend der Vererbung aufgerufen werden.

Für eine Reihe von Objektinstanzen, dass die Reihenfolge Objekte zerstört werden, ist die Umkehrung der Reihenfolge des Aufbaus. Dies ist leicht zu überprüfen, wie der folgende Code zeigt. Eine Klassenvariable verfolgt die Gesamtzahl der erstellten Instanzen und ein Datenelement für jedes Objekt verfolgt seine eigene Nummer. Der Konstruktor und der Destruktor geben eine Nachricht aus, sodass wir bei der Ausführung genau sehen können, was wann passiert.

Der Testcode gibt die Anzahl der Objekte von 0 bis 9 beim Konstruieren aus und dann von 9 bis 0, wenn die Instanzen zerstört werden. (Dies wurde mit g++-4.2 unter Mac OS X getestet)

#include <iostream> 

class MyClass 
{ 
public: 

    MyClass() 
    { 
     mCounter = kInstanceCount++; 
     std::cout << "+++ MyClass() " << mCounter << std::endl; 
    } 

    ~MyClass() 
    { 
     std::cout << "--- MyClass() " << mCounter << std::endl; 
    } 

private: 
    unsigned   mCounter; 
    static unsigned  kInstanceCount; 
}; 

unsigned MyClass::kInstanceCount = 0; 

int main() 
{ 
    MyClass arr[10]; 
    return 0; 
} 

Sie müßten den C++ Standard überprüfen, da ich nicht 100% sicher bin, dass dies nicht eine Implementierung Detail (wie es oft der Fall ist) In diesem Fall möchten Sie sich nicht auf dieses Verhalten verlassen.

Beachten Sie auch, dass es nicht so üblich ist, ein stackbasiertes Array von tatsächlichen Objektinstanzen zu erstellen. Sie verwenden eher std::vector oder verwenden möglicherweise Smartpointer für Heap-allocated-Objekte.