2009-03-17 5 views
5

Ho una classe che crea un oggetto all'interno di un metodo pubblico. L'oggetto è privato e non visibile agli utenti della classe. Questo metodo quindi chiama altri privati ​​ metodi all'interno della stessa classe e passare l'oggetto creato come parametro:Passare un puntatore intelligente come argomento all'interno di una classe: scoped_ptr o shared_ptr?

class Foo { 
    ... 
}; 

class A { 
    private: 
     typedef scoped_ptr<Foo> FooPtr; 

     void privateMethod1(FooPtr fooObj); 

    public: 
     void showSomethingOnTheScreen() { 
      FooPtr fooObj(new Foo); 
      privateMethod1(fooObj); 
     }; 
}; 

Credo che il puntatore intelligente corretto in questo caso sarebbe uno scoped_ptr, però, non posso fare questo perché scoped_ptr rende la non copiabili classe, se usato in questo modo, quindi dovrei fare i metodi come questo:

void privateMethod1(FooPtr& fooObj); 

privateMethod1 non memorizza l'oggetto, né mantiene i riferimenti di esso. Recupera solo i dati dalla classe Foo.

Probabilmente il modo corretto sarebbe non utilizzare affatto un puntatore intelligente e allocare l'oggetto nello stack, ma ciò non è possibile perché utilizza una libreria che non consente oggetti nello stack, che devono essere nell'heap .

Dopotutto, sono ancora confuso riguardo al reale utilizzo di scoped_ptr.

+1

Sono curioso della libreria che "non consente oggetti in pila". Gli oggetti sono allocati all'interno della libreria sullo heap con una fabbrica? La libreria diventa proprietaria del puntatore e lo elimina?Quali sono i motivi per cui non è possibile utilizzare gli oggetti allocati nello stack? –

risposta

1

Utilizzare qui semplice std :: auto_ptr poiché non è possibile creare oggetti nello stack. Ed è meglio per la tua funzione privata accettare semplicemente il puntatore raw.

L'utilizzo reale è che non è necessario prendere tutte le eccezioni possibili e fare l'eliminazione manuale.

In realtà, se l'oggetto è non modificare l'oggetto e l'oggetto di ritorno API di sicuro è meglio usare

void privateMethod1(const Foo& fooObj); 

e passare l'oggetto lì come

privateMethod1(*fooObj.get()); 
+0

Questo fine è esattamente uguale a scoped_ptr, solo che non obbliga a dichiarare i parametri del metodo come riferimenti. Ma se non lo fai, si romperà in modi sorprendenti (fooObj sarà un puntatore Null una volta restituito privateMethod1, anche se ci sono più cose che ti piacerebbe fare con esso). – sth

+0

concordato con sth se corso. perché usare auto_ptr se scoped_ptr è chiaramente la scelta migliore? il trasferimento di proprietà non era destinato. –

+0

Ragazzi, non ho una spinta sul mio progetto. Ecco perché ho proposto una tale soluzione. Dove vedi il "trasferimento di proprietà"? –

1

I' m sospettoso del commento "usa una libreria che non ammette oggetti in pila, devono essere nell'heap".

Perché? Questo in genere significa che devono essere deallocati in un modo speciale, quindi forse nessuna di queste soluzioni funzionerà.

+0

@Earwicker il compilatore che stiamo usando è Borland C++ e la libreria che stiamo usando è la libreria VCL GUI che è in bundle con C++. Questo cambierà presto, ma per ora devo attenermi a questo. Per qualche motivo, VCL deve essere allocato sull'heap, non ho una vera idea del perché. –

+0

Probabilmente significa che la libreria ha metodi di fabbrica che restituiscono puntatori agli oggetti creati e passano all'utente. –

+0

Sei sicuro di aver bisogno di eliminare gli oggetti? Non ho mai usato VCL, ma ho la vaga idea che cancelli i componenti automaticamente quando i loro genitori vengono cancellati. –

3

Un'ulteriore possibilità è quella di creare l'oggetto come static_ptr per facilità di gestione della memoria, ma solo passare il puntatore grezzo agli altri metodi privati:

void privateMethod1(Foo *fooObj); 

void showSomethingOnTheScreen() { 
    scoped_ptr<Foo> fooObj(new Foo); 
    privateMethod1(fooObj.get()); 
}; 
3

userei scoped_ptr all'interno showSomethingOnTheScreen, ma passare un puntatore (o riferimento) crudo a privateMethod1, ad es

scoped_ptr <Foo> fooObj (nuovo Foo);
privateMethod1 (fooObj.get());

+0

Questa era la mia ipotesi reale, ma questa pratica è raccomandata? Se è questo è quello che farò –

0

In tal caso, è sufficiente sostituire il meccanismo di assegnazione.
Creare l'oggetto nell'heap, ma passare l'oggetto come riferimento ai metodi privati.

class A { 
    private: 
     void privateMethod1(Foo& fooObj); 

    public: 
     void showSomethingOnTheScreen() { 
      scoped_ptr<Foo> fooObj(new Foo); 
      privateMethod1(*(fooObj.get())); 
     }; 
};