2015-05-10 9 views
5

ho notato che se ho il seguente:Utilizzando unique_ptr come un parametro di metodo - Pro e contro

#include <memory> 
using namespace std; 

class Foo 
{ 
public: 
    Foo(); 
}; 

class Wobble 
{ 
public: 
    void SetWibble(unique_ptr<Foo> foo) 
    { 
     this->wibble = move(foo); 
    } 

    // I like returning a ref as it gives control to 
    // the user of my framework over recieving a & or a copy 
    Foo& GetWibble() 
    { 
     return *wibble; 
    } 

    unique_ptr<Foo> wibble; 
}; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    unique_ptr<Wobble> wobble;  

    unique_ptr<Foo> foo(new Foo()); // Look here 
    foo->something = ...; 
    foo->something1 = ...; 
    foo->something2 = ...; 

    wobble->SetWibble(move(foo)); 

    return 0; 
} 

... quando dichiaro foo, ho un oggetto piacevole Foo .. e quando ho move sua proprietà nell'istanza wobble, foo è ora vuoto nell'ambito int _tmain.

Ho molto apprezzato questo come ho pensato che stava rimuovendo la memoria e di compensazione il puntatore dal int _tmain ambito ... che nel mio contesto attuale non dovrebbe essere necessario giocherellava con qualsiasi altro ... Al contrario di questo:

// ... 
void SetWibble(Foo& foo) 
{ 
    this->wibble = foo; 
} 
// ... 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    unique_ptr<Wobble> wobble; 

    Foo foo; 
    foo.something = ...; 
    foo.something1 = ...; 
    foo.something2 = ...; 

    wobble->SetWibble(foo); 

    return 0; 
} 

Che conserva ancora un riferimento a tale variabile all'interno dell'ambito.

D:

  1. è quello che ho detto sopra è corretto?
  2. Mi chiedo se ci sono dei vantaggi sull'uso di unique_ptr e non sull'uso di unique_ptr qui oltre a quelli che ho indicato?
+4

si sarebbe probabilmente trovare questo interessante: http://herbsutter.com/2013/06/05/gotw-91-solution-smart-pointer-parameters/ – Galik

+0

mi accingo a leggere questo correttamente questa volta, mi penso di essere stato indirizzato al suo prima ... – Jimmyt1988

+2

Dimentichi che in un caso stai usando l'heap e nell'altro lo stack, la scelta dipende dall'applicazione. – dlavila

risposta

0

La differenza principale tra i due esempi non è l'uso di std::unique_ptr ma l'utilizzo di allocazione dinamica della memoria rispetto all'allocazione nello stack.

In genere è preferibile allocare oggetti in pila. Eviterete il costo di un'allocazione dinamica della memoria e l'indecisione non necessaria di un puntatore (non vedo alcun motivo per non assegnare Wobble allo stack per l'avvio).

Se sono solo preoccupati di avere una variabile nel vostro ambito forse si potrebbe estrarre la creazione di Foo ad una funzione separata:

Foo createFoo() { 
    Foo foo; 
    foo.something = ...; 
    foo.something1 = ...; 
    foo.something2 = ...; 
    return foo; 
} 

int main() { 
    Wobble wobble; 
    wobble.SetWibble(createFoo()); 
} 

In alternativa, se Foo è mobile, è possibile spostare direttamente al posto di spostamento di un std::unique_ptr<Foo>:

int main() { 
    Wobble wobble; 

    Foo foo; 
    foo.something = ...; 
    foo.something1 = ...; 
    foo.something2 = ...; 

    wobble.SetWibble(std::move(foo)); 
} 

Se si esegue questa operazione si potrebbe desiderare di ottimizzare SetWibble per i riferimenti R-valore. Anche se non vi è alcun particolare vantaggio in termini di efficienza nello spostamento di foo, è almeno necessario documentare che non si debba più manipolare la variabile.

Se Foo non è mobile ed è costoso da copiare, allora sì, potrebbe esserci un motivo per allocare la memoria in modo dinamico. E, sì, se hai intenzione di allocare la memoria in modo dinamico, è buona pratica gestire quella memoria con std::unique_ptr.

Off-topic:

  • Nel vostro primo esempio, fare attenzione dereferenziazione wibble in GetWibble. Avete una garanzia che lo wibble non è nullo? Non avrebbe mai potuto essere impostato, o avrebbe potuto essere impostato esplicitamente su nullptr Forse questa è una precondizione di chiamare GetWibble ma è un esempio di come la ricerca indiretta extra di un puntatore può aggiungere complicazioni.
  • Nel secondo esempio sarebbe più idiomatico per SetWibble prendere un riferimento const.