2015-05-13 10 views
5

Ad esempio, sono abbastanza sicuro che funzioni.Se prendo un puntatore raw di un unique_ptr e poi utilizzo reset, il puntatore raw è ancora garantito valido?

int foo = 51; 
int* bar = &foo; 
foo = 3; 

Quindi la barra è ancora valida e *bar == 3.

Che dire se diciamo

std::unique_ptr<int> foo(new int(51)); // should probably use make_unique 
int* bar = foo.get(); 
foo.reset(new int(3)); 

Perchè sono garantiti che *bar == 3? Oppure sto causando un comportamento indefinito continuando alla barra di riferimento?

risposta

8

No, per niente. Si otterrà un comportamento non definito, poiché il puntatore raw gestito da unique_ptr viene modificato da reset. Infatti, lo unique_ptr elimina il puntatore gestito e ne ridistribuisce uno nuovo, quindi il vecchio puntatore continuerà a puntare al vecchio indirizzo, che non è più valido. Il tuo codice è equivalente a questo:

#include <iostream> 

int main() 
{ 
    int* managed = new int(51); // equivalent to unique_ptr(new int(51)); 
    int* bar = managed; // equivalent of unique_ptr::get 
    delete managed; managed = new int(3); // equivalent to unique_ptr::reset(new int(3)) 
    std::cout << *bar << std::endl; // Wrong!!! Undefined behaviour, bar is dangling! 
} 

Il tuo primo frammento di codice è effettivamente corretto, dal momento che non si cambia qualsiasi indirizzo lì, si sta solo cambiando la variabile il puntatore punta a, così naturalmente dereferenziazione puntatore otterrà tu il valore aggiornato.

7

No, se si reimposta uno unique_ptr, verrà eliminato il puntatore che possiede.

si può fare:

int* bar = foo.release(); 

Questo fa sì che foo rinunciare alla proprietà del suo puntatore e restituirlo.

+0

Se imposto 'bar = foo.get()' e poi decido che cambierò pippo, posso semplicemente chiamare 'foo.release()' e lasciare che la barra assuma la proprietà senza assegnazione esplicita? Non riesco davvero a pensare a un caso d'uso, ma sono curioso di sapere se funzionerà correttamente. – wrhall

+1

@wrhall: No, non puoi. Sarebbe tremendamente pericoloso. Unique_ptr * always * possiede il puntatore. Questo è il solo scopo. Puoi solo evitarlo usando 'release()', che è una funzione terribile che non dovresti mai chiamare. – Puppy

+0

@Puppy anche se è una cattiva pratica, è tecnicamente corretto? Guardando la documentazione, sembra che 'release()' * rilasci la proprietà dell'oggetto gestito, se presente. get() restituisce 'nullptr' dopo la chiamata. * Quindi mi sembra che' release() 'esegua davvero' return managed_ptr; 'e contrassegna' unique_ptr' come "non-managing", quindi future 'get()' ritorna 'nullptr'. Sai se questo è davvero il caso? – vsoftco

Problemi correlati