2012-04-02 11 views
9

This answer citazioni C++ 11 standard 3.8:Perché non si elimina un oggetto che ha un distruttore con un comportamento non definito di effetto collaterale in C++ 11?

se v'è alcuna chiamata esplicita alla distruttore o se un delete-espressione (5.3.5) non viene utilizzato per rilasciare l'archiviazione, il distruttore non sarà implicitamente chiamato e qualsiasi programma che dipende dagli e ff etti laterali prodotti dal distruttore ha un comportamento indefinito.

La parte sul distruttore che non viene chiamata è chiara. Ora supponiamo che il distruttore saltato abbia avuto un effetto collaterale che avrebbe dovuto influenzare il comportamento del programma.

Perché il comportamento del programma non è definito ora? Perché gli effetti collaterali non dovrebbero essere saltati (poiché il distruttore non viene chiamato) e il programma funziona normalmente solo senza effetti collaterali applicati?

+2

Interessante domanda. Ma perché qualcuno non vorrebbe chiamare il distruttore su un oggetto quando non è più necessario? – ereOn

+1

Se il distruttore in questo caso esegue attività non banali per ex: la chiusura degli handle delle risorse o lo stato di impostazione su qualcosa di valido ecc., Il distruttore non viene chiamato will ofcourse influenza il programma e genererà un comportamento indefinito.Non capisco la logica per saltare gli effetti collaterali. –

+0

@ereOn: Singletons è stato menzionato come caso d'uso (tuttavia, questo non dovrebbe essere considerato un buon design). –

risposta

5

La parte importante è la prima parte di questo paragrafo (sottolineatura mia):

Un programma può porre fine alla vita di un qualsiasi oggetto dal riutilizzando lo stoccaggio cui l'oggetto occupa ...

Se si riutilizza semplicemente lo spazio di archiviazione per un oggetto il cui distruttore ha non chiamato, si ottiene un comportamento non definito. Ad esempio, l'oggetto potrebbe aver avviato un thread o registrato un callback o qualche altra azione in cui un componente esterno potrebbe aspettarsi che l'oggetto esista ancora.

+2

Non sono d'accordo. La citazione completa aggiunge * o chiamando esplicitamente il distruttore per un oggetto di un tipo di classe con un distruttore non banale *. Quindi il distruttore verrebbe chiamato in questo caso. –

+0

scusa, nel qual caso? Dice ** o **, quindi la mia citazione sopra sembra stare da sola e anche la tua. –

+0

Ma questo è il problema a cui sto puntando. Né la citazione * si regge da sola *. Lo standard offre un'alternativa, ma la scelta non è nostra. Il * per un oggetto di un tipo di classe con un distruttore non banale * fornisce il criterio per selezionare tra i due rami del ** o **. E quindi qualsiasi oggetto con un distruttore non trittico (che è il caso interessante qui) otterrà il suo distruttore chiamato * prima * il suo spazio di archiviazione viene riutilizzato. –

1

La tua domanda non ha senso.

Perché gli effetti collaterali non vengono ignorati (poiché il distruttore non viene chiamato) e il programma viene eseguito normalmente solo senza effetti collaterali applicati?

Vengono saltati, perché sarebbero stati attivati ​​dal distruttore e non è stato chiamato.

La mia lettura di:

e qualsiasi programma che dipende dai etti ff lato e prodotte dal distruttore ha fi nito comportamento unde.

è semplice, lo vedo alla luce di RAII. Esempio:

#include "Object.hpp" 

struct Manager: private boost::noncopyable { 
    union Raw { 
    char _[sizeof(Object)]; 
    Object o; 
    }; 
    static Raw raw; 

    Manager() { new (raw.o) Object(); } 
    ~Manager() { raw.o.~Object(); } 
}; 

Ora, se io allocare una Manager, dimentica di distruggerlo, e alloca uno nuovo, io sono in un pizzico di sto sovrascrivere la memorizzazione del primo creato Object con un secondo anche se è ancora "vivo". Questo è un comportamento indefinito.

1

Credo che questo sia inserito nello standard per consentire la garbage collection. E per sottolineare che C++ si comporta diversamente da altri linguaggi, non chiamando i distruttori durante la raccolta.

Specifica in modo specifico che lo spazio di archiviazione può essere riutilizzato senza chiamare i distruttori degli oggetti in quell'area di memoria. Se il programma dipende da sui distruttori in esecuzione, non funzionerà come previsto.

Se il valore non dipende da dipende dai distruttori, tutto va bene.

3

In questo caso, abbiamo una risposta precisa. La linea specifica è stata introdotta per risolvere CWG 1116, "Aliasing dei membri del sindacato".

Problemi correlati