2016-11-21 5 views
7

Ich habe Klasse Item die ihre eigenen Betreiber neue und Betreiber löschen wie folgt definiert:Wird der Destruktor implizit in einer überladenen Operator-Löschfunktion aufgerufen?

class Item 
{ 
public: 
    Item(const std::string &s):msg(s) 
    { 
     std::cout<<"Ctor: "<<msg<<std::endl; 
    } 
    static void* operator new(size_t size, int ID, const std::string &extra) 
    { 
     std::cout<<"My Operator New. ID/extra: "<<ID<<"/"<<extra<<std::endl; 
     return ::operator new(size); 
    } 
    static void operator delete(void* p) 
    { 
     std::cout<<"My Operator Delete"<<std::endl; 
     return; 
    } 
    ~Item() 
    { 
     std::cout<<"Destructor: "<<msg<<std::endl; 
    } 
    void Print() 
    { 
     std::cout<<"Item::msg: "<<msg<<std::endl; 
    } 
private: 
    std::string msg; 
}; 

ich ein Objekt dieses Typs erstellen, indem Sie eine Platzierung neuer und anschließend löschen, wie folgt:

int main() 
{ 
    Item *pI=new(1,"haha")Item("AC Milan"); 
    std::cout<<"before delete"<<std::endl; 
    delete pI; 
    std::cout<<"after delete"<<std::endl; 
    return 0; 
} 

die Ausgabe lautet:

My Operator New. ID/extra: 1/haha 
Ctor: AC Milan 
before delete 
Destructor: AC Milan 
My Operator Delete 
after delete 

Wie Sie sehen können, delete pI meine eigene Löschfunktion aufruft, in dem nothi ng wird ausgeführt, außer dass ein Protokoll ausgegeben wird. Von der Ausgabe wird jedoch der Destruktor Item in delete pI aufgerufen, der in meiner eigenen Löschfunktion nicht aufgerufen wird.

In diesem Fall würde Destruktor implizit in einer überladenen Löschfunktion aufgerufen werden?

+0

Ich benutze g ++ 4.9.3 –

+0

Es ist das gleiche für Ihre "neue" und Ihre "delete" -Operatoren. Sie rufen den Konstruktor in Ihrem überladenen 'new'-Operator auch nicht auf und er wird immer noch aufgerufen. Die Konstruktoren und Destruktoren werden immer aufgerufen, wenn die Operatoren 'new' und' delete' verwendet werden. –

+2

Speicherzuordnung und Objekterstellung/-zerstörung sind zwei verschiedene Dinge. Das Überladen der Zuordnungsfunktionen wirkt sich nur auf erstere aus; Letzteres wird vollständig von den Kernsprachenregeln gesteuert. –

Antwort

4

In diesem Fall würde Destruktor implizit in einer überladenen Löschfunktion aufgerufen werden?

Ja. Für eine delete expression, (1) wird zuerst der Destruktor aufgerufen, dann (2) wird der entsprechende operator delete aufgerufen; Nachschlagen von Namen und Überladung wird zu diesem Zeitpunkt durchgeführt.

Wenn Ausdruck nicht ein Nullzeiger ist, ruft der Lösch-Ausdruck den destructor (falls vorhanden) für das Objekt, das zerstört werden wird oder für jedes Element des Feldes zerstört wird (von dem letzten Elemente zu dem ersten Elemente verläuft des Arrays).

Danach, es sei denn, die passende neue-Expression wurde mit einem anderen neuen Ausdruck kombiniert (da C++ 14) der Lösch-Ausdruck, der die Aufhebung der Zuordnung Funktion entweder operator delete (für die erste Version des Ausdrucks) oder operator delete[] aufruft (z die zweite Version des Ausdrucks).

0

So in diesem Fall würde destructor implizit in einer überladenen Löschfunktion aufgerufen werden?

Destruktoren und überladene Löschoperatoren interagieren auf komplizierte Weise. Wenn Sie sagen,

delete pI; 

diese kompiliert tatsächlich auf einen Aufruf Ihres destructor, und kein Bezug genommen auf „Löschen“.

Ihr Destruktor hat (GCC) zwei Instanzen im VTable (wenn virtuell) oder (MSVC) ein boolesches Argument. Die Instanzen/bool werden verwendet, um zu bestimmen, ob der so kompilierte Destruktor ein Lösch- oder ein nicht löschender Destruktoraufruf sein sollte. Wie Sie sich vorstellen können, ist der Löschdestruktor dann dafür verantwortlich, den Link-Time-Operator für Sie zu löschen. Wenn Sie

geschrieben habe
pI->~Item(); 

Sie würden den Nicht-Löschen destructor zu laufen (den anderen VTable-Eintrag, oder mit dem boolean gespiegelt) haben zusammengestellt.

Da Ihr Destruktor nicht virtuell ist, ist es wahrscheinlich sowieso alles inline.Das Verhalten wird jedoch davon nicht unterscheidbar sein. Wenn Ihr Destruktor virtuell ist, ruft der Löschvorgang den richtigen Löschvorgang für den tatsächlich vorhandenen Dateityp auf, anstatt den Zeigertyp zu löschen, bei dem Sie löschen aufrufen.

+0

Der Vollständigkeit halber gibt es einen dritten Destruktor, der benutzt wird, um deine Klasse zu zerstören, aber nicht deine virtuellen Basen. Es ist in dieser Diskussion nicht relevant, da Sie keine virtuellen Basen haben. – dascandy

1

Der Destruktor wird nicht von einer überladenen operator delete() Funktion aufgerufen.

jedoch ein delete Ausdruck (in Ihrem Fall delete pI) hat die Wirkung des ersten den destructor für das Objekt aufgerufen wird, und dann die entsprechende Überlastung der operator delete() aufrufen.

Verwandte Themen