2016-03-17 27 views
10

Questo codice è quello che voglio fare:Cosa succede a unique_ptr dopo std :: move()?

Tony& Movie::addTony() 
{ 
    Tony *newTony = new Tony; 
    std::unique_ptr<Tony> tony(newTony); 
    attachActor(std::move(tony)); 
    return *newTony; 
} 

mi chiedo se avrei potuto fare questo, invece:

Tony& Movie::addTony() 
{ 
    std::unique_ptr<Tony> tony(new Tony); 
    attachActor(std::move(tony)); 
    return *tony.get(); 
} 

ma sarà *tony.get() essere lo stesso puntatore o nulla? So che potrei verificare, ma qual è la cosa standard da fare?

+0

Perché stai 'move()' 'ing' the unique_ptr' in 'attachActor()' per cominciare? Cosa fa effettivamente 'attachActor()'? –

risposta

15

No, non è possibile farlo. Lo spostamento di unique_ptr lo annulla. Se così non fosse, allora non sarebbe unico. Sto ovviamente dal presupposto che attachActor non fare qualcosa di stupido come questo:

attachActor(std::unique_ptr<Tony>&&) { 
    // take the unique_ptr by r-value reference, 
    // and then don't move from it, leaving the 
    // original intact 
} 

Sezione 20.8.1 paragrafo 4.

Inoltre, u (l'oggetto unique_ptr) possono, su richiesta, il trasferimento proprietà su un altro puntatore univoco u2. Al termine di tale trasferimento , i seguenti postcondizioni tengono:
      - u2.p è uguale al pre-trasferimento up,
      - up è uguale a nullptr e
      - se lo stato pre-trasferimento ud mantenuto, tale stato è stato trasferito a u2.d.

+0

Tuttavia, probabilmente non è una buona idea avere una funzione che richieda 'unique_ptr &&' comunque (oltre a move-constructor e move-assigners). – Rufflewind

+0

@ Rufflewind: concordato –

+0

@ BenjaminLindley, grazie per la risposta! Sì, attachActor() prende std :: unique_ptr , niente di speciale. – user3496846

7

Lo standard dice (§   20.8.1.2.1 ¶   16, il corsivo è mio) che il costruttore mossa di std::unique_ptr

unique_ptr(unique_ptr&& u) noexcept; 

Costruisce un unique_ptr da trasferimento della proprietà da u a *this.

Pertanto, dopo aver spostato-costruire l'oggetto temporaneo che viene passato come argomento al attachActor formare il vostro tony, tony non possiede più l'oggetto e quindi tony.get() == nullptr. (Questo è uno dei pochi casi in cui la libreria standard effettivamente fa asserzioni sullo stato di un oggetto spostato da).

Tuttavia, il desiderio di restituire il riferimento può essere soddisfatto senza ricorrere a n. new e raw puntatori.

Tony& 
Movie::addTony() 
{ 
    auto tony = std::make_unique<Tony>(); 
    auto p = tony.get(); 
    attachActor(std::move(tony)); 
    return *p; 
} 

Questo codice presuppone che attachActor non cadrà sua tesi sul pavimento. In caso contrario, il puntatore p ciondolerebbe dopo attachActor ha return ed. Se non si può fare affidamento su questo, dovrai ridefinire la tua interfaccia e utilizzare invece i puntatori condivisi.

std::shared_ptr<Tony> 
Movie::addTony() 
{ 
    auto tony = std::make_shared<Tony>(); 
    attachActor(tony); 
    return tony; 
} 
+0

Il trasferimento di proprietà non implica che 'u' non possieda nulla, solo che non possiede più l'oggetto di sua proprietà prima. Se questo fosse l'unico requisito, il trasferimento potrebbe avvenire semplicemente ** scambiando ** la proprietà dell'oggetto tra 'u' e' * this' (che è ciò che fanno altri costruttori di mosse per impedire qualsiasi allocazione e deallocazione). Ma come osserva Benjamin Lindley, ci sono requisiti aggiuntivi su std :: unique_ptr oltre al semplice "trasferimento di proprietà" testuale. – Dreamer