2011-12-20 17 views
8

Mi chiedevo quale parte del mio codice liberasse un membro di classe assegnato dinamicamente, ma statico quando questo non è più necessario. Vedere il seguente codice: classPrinter è condiviso tra tutti gli oggetti A e creato quando verrà creata la prima istanza della classe A. Solo per essere sicuri: l'oggetto classPrinter verrà automaticamente distrutto quando si esce dal mio programma, giusto?Membro della classe statica C++, che pulisce il pasticcio?

a.h

class A { 
static B* classPrinter; 
} 

a.cpp

#include "a.h" 
B A::classPrinter = new B(); 

A::A() { ...} 
+3

I puntatori intelligenti fanno bene a questo tipo di cose, almeno se si ha realmente bisogno dell'allocazione dinamica (vedere [risposta di sbi] (http://stackoverflow.com/a/8578256/10077). –

+1

Ack .... statico pointer == evil –

risposta

19

Solo per essere sicuri: l'oggetto somePrinter verrà automaticamente distrutto quando si esce dal mio programma, giusto?

Poiché questo è C++, la risposta è "No". Per tutto ciò che è stato assegnato con new, è necessario chiamare il corrispondente delete. Se ciò non accade, l'oggetto perde. Ma perché allocarlo dinamicamente? Questo

class A { 
    static B classPrinter; 
} 

B A::classPrinter; 

si comporta come il codice, se non che classPrinter sarà distrutta alla fine del programma.

Tuttavia, lei scrive che

classPrinter è condivisa tra tutti A-oggetti e crea quando verrà creata la prima istanza di class A.

Il codice nella tua domanda non lo fa. Se si vuole fare questo, fare qualcosa di simile:

class A { 
    static std::shared_ptr<B> classPrinter; 
} 

std::shared_ptr<B> A::classPrinter; 

A::A() 
{ 
    if(!classPrinter) 
    classPrinter.reset(new B()); 
} 

Il puntatore intelligente farà in modo che l'oggetto viene eliminato.

+1

"è condiviso tra tutti oggetti e creati quando verrà creata la prima istanza della classe A " – pezcode

+0

@pezcode: suppongo che tu faccia riferimento a" creato quando verrà creata la prima istanza della classe A. "L'ho letto, ma il codice nella domanda fa lo stesso come il mio codice (ad eccezione di perdite, ovviamente). – sbi

+0

potrebbe essere un nuovo operatore è sovraccarico, penso che non sia un caso, ma in teoria è possibile. – Yola

3

Il distruttore dell'oggetto di cui A::classPrinter punti non saranno chiamati.

Se ci pensate non è nient'altro che logica; dov'è l'abbinamento delete -statement che, in casi normali, chiamerebbe il dtor dell'oggetto?

La memoria occupata verrà contrassegnata come nuovamente libera e restituita al sistema, almeno in tutti i moderni.

+0

@sbi Non sono sicuro se ho avuto la possibilità di modificare il mio post prima o dopo il tuo commento, ma ho cambiato la dicitura in modo che fosse più facile da capire. –

0

Se A::classPrinter è condiviso tra più membri, è possibile utilizzare std :: shared_ptr anziché un puntatore raw? Sarà cancellato automaticamente dopo che tutti i riferimenti a esso sono andati.

Ma sì, la memoria verrà recuperata dopo l'uscita del programma, almeno su tutti i sistemi operativi che posso pensare ...

0

È necessario creare un po 'di involucro o usare qualcosa come shared_ptr per garantire dtor chiamata.

10

No, gli oggetti creati utilizzando new non vengono mai eliminati automaticamente.È sempre necessario fornire un valore corrispondente a delete per evitare perdite di memoria.

In questo caso, la soluzione più semplice sarebbe avere un oggetto statico, piuttosto che un puntatore statico a un oggetto dinamico - non vi è alcuna ragione per il livello aggiuntivo di riferimento indiretto.

// header file 
class A { 
    static B classPrinter; 
}; 

// source file 
B A::classPrinter; 

o se si vuole ritardare la costruzione fino è necessaria l'oggetto (e di evitare potenziali problemi se oggetti statici in altre unità di traduzione hanno bisogno di accedere dai loro costruttori):

class A { 
    static B & classPrinter() { 
     static B instance; 
     return instance; 
    } 
}; 

In altre situazioni, quando è effettivamente necessaria l'allocazione dinamica, è necessario gestire sempre l'oggetto dinamico utilizzando i puntatori intelligenti o altri oggetti RAII.

+1

Quella statica locale è un bel trucco che ho dimenticato di menzionare. '+ 1' da me. – sbi

0

Statico (per quanto riguarda la variabile membro statica) intrinsecamente significa, esiste sempre.

Se si crea un puntatore statico, non è possibile rilasciarlo in un punto che ha senso. Hai bisogno di più contesto.

Se si desidera che i dati condivisi esistano solo mentre sono presenti istanze di classe del proprietario membro statico, è necessario un contatore statico. Assegna un nuovo valore statico ogni volta che crei un'istanza e un contatore == 0. Alloca il valore statico corrente ogni volta che elimini l'ultima istanza della classe proprietario.

In caso contrario, sarà necessario immergersi in elementi come puntatori condivisi o intelligenti per deallocare, ma anche in questo caso si incontrano problemi. Se il puntatore intelligente non vede più riferimenti e deallocati, potrebbe farlo troppo presto. Se si trova nello stato deallocato, cosa significa quando hai di nuovo bisogno delle informazioni. Assegni un nuovo valore statico?

Se il membro statico deve sempre esistere se si dispone di un'istanza della classe del proprietario o meno, è consigliabile prendere in considerazione la modifica del puntatore in un riferimento o un'istanza.

Problemi correlati