2011-02-07 13 views
14

Perché è possibile creare un oggetto di una classe con distruttore privato nel negozio gratuito ma non nello stack?Distruttore privato

Per esempio, questo è illegale:

class Foo 
{ 
public: 
    explicit Foo(int); 
    static void delete_foo(Foo* foo) { delete foo; } 
private: 
    int x; 
    ~Foo(); 
    Foo(const Foo&); 
    Foo& operator=(const Foo&); 
}; 

int main() 
{ 
    Foo * fooptr = new Foo(5); // legal 
    Foo::delete_foo(fooptr); // legal 
    Foo foo(5); // illegal 
} 
+0

Potrebbe fornire un esempio di codice breve per l'illustrazione? – sharptooth

+0

Posso farlo per voi – CashCow

risposta

18

Quando si crea in pila, esso deve essere distrutto prima che la funzione può restituire. Presumendo che la funzione in questione non abbia accesso al distruttore, questo non è permesso.

Quando lo si crea nel negozio gratuito, viene lasciato per altro codice, che ha accesso al distruttore, per distruggerlo.

Una funzione membro di una classe con un distruttore privato può creare un'istanza nello stack. Una funzione membro statica può anche essere chiamata senza un'istanza preesistente. Non c'è probabilmente una buona ragione per scrivere una cosa del genere, però.

+0

+1 per la sfumatura della funzione membro. – GManNickG

+1

@Potatoswatter: può essere utile forzare l'utente ad accedere all'oggetto tramite un proxy 'amico'. Sembra limitato però. –

+1

@ Matthieu: Sì, avrei dovuto dirlo. Ci sono buone ragioni per scrivere un distruttore privato.Intendevo solo che raramente una funzione membro statica crea un'istanza temporanea, o che tale oggetto sarà collocato sullo stack. – Potatoswatter

2

Perché la creazione di un oggetto nell'archivio gratuito non richiede un distruttore pubblico, ma la sua creazione nello stack avviene perché gli oggetti verranno distrutti quando si spegne. È possibile creare l'oggetto nel negozio gratuito, ma non è possibile eliminarlo, quindi si verificherà una perdita di memoria a meno che l'oggetto o la funzione di amico non lo distruggano.

9

Poiché un oggetto con memoria automatica * deve essere, beh, automaticamente distrutto. Quindi il distruttore deve essere disponibile per chiamare; se non lo è, non puoi avere quel tipo nella memoria automatica.

Al contrario, spetta a te eliminarlo quando lo si assegna dinamicamente. Ovviamente puoi non farlo.

* Gli oggetti sono, su piattaforme "tipiche", comunemente allocati sullo stack.

1

È possibile crearne uno nello stack solo nell'ambito che ha accesso al distruttore. Pertanto è possibile farlo in una funzione amico o in una funzione membro statico della classe (o anche in un membro della classe normale).

La fine della funzione per una variabile locale è responsabile dell'eliminazione pertanto deve essere in grado di chiamare il distruttore, anche se implicitamente.

È possibile crearne uno con nuovo da qualsiasi luogo se si ha accesso al costruttore appropriato.

Se lo si utilizza in un puntatore intelligente, è necessario assicurarsi che l'accesso venga eliminato. Questo può variare per diversi puntatori intelligenti e per alcuni è possibile fornire un distruttore personalizzato che potrebbe essere un membro statico della classe.

0

Perché è possibile applicare che un oggetto viene sempre assegnato dinamicamente, cioè con un nuovo operatore. Per fare questo lavoro è necessario implementare un metodo dispose() che chiama "delete this" prima che ritorni. Ciò rende possibile la creazione di metodi finalizzati chiamati prima che un oggetto o una parte di un oggetto vengano distrutti e quindi in grado di eliminare o disconnettere in modo sicuro i membri dell'istanza prima che venga chiamata la catena virtuale dei distruttori.