2015-09-23 25 views
5

preso da una diapositiva a cppcon2015:Impedire dereferenziazione non sicuro di std :: unique_ptr

unique_ptr<A> f() { 
    auto a = make_unique<A>(); 
    return a; 
} 

//Why does this even compile? 
const A & dangling = *f(); 

//BOOM!!! 
use(dangling); 

La mia domanda è: con i riferimenti rvalue per * questo, può risolvere il problema?

vedo nelle specifiche in cppreference:

typename std::add_lvalue_reference<T>::type operator*() const; 

Domanda:

  1. Avrebbe senso per non consentire operator* per rvalue unique_ptr s e hanno solo dereferenziare valido per lvalue unique_ptr s?
  2. Ci sono ancora casi d'uso validi per mantenere il valore unique_ptr cancellabile?

Ti piace questa:

//Make sure it is an lvalue. 
typename std::add_lvalue_reference<T>::type operator*() const &; 

NOTA: Non sono sicuro della sintassi o correttezza, non ho alcuna esperienza con i riferimenti rvalue per questo *.

+3

Forse vuoi dire '* f();' invece di 'f();'? –

+0

btw. 'const &' consentirebbe comunque all'oggetto implicito di essere un valore rvalore –

+1

E a proposito di 'auto non_dangling = f()' per evitare il problema? È davvero il puntatore che deve essere risolto? –

risposta

3

La mia domanda è: con i riferimenti di rvalue per *this, può essere risolto?

Tecnicamente sì. Una soluzione potrebbe essere quella di introdurre un sovraccarico aggiuntivo (cancellato) per rvalues:

typename std::add_lvalue_reference<T>::type operator*() const&& = delete; 
//              ~~~~~~~~~~~~~~~^ 

e per modificare l'esistente mediante l'aggiunta di un ref-qualificazione:

typename std::add_lvalue_reference<T>::type operator*() const&; 
//               ~~^~~ 

Dal rvalues ​​preferiscono fortemente essere vincolato da un riferimento di rvalue, qualsiasi tentativo di dereferenziazione di un'espressione rvalue che coinvolge uno unique_ptr comporterebbe un errore di compilazione - "uso della funzione eliminata".

Avrebbe senso per non consentire operator* per rvalue unique_ptrs e hanno solo dereferenziare valido per lvalue unique_ptrs?

Non sempre. E a causa di ciò dubito che la libreria debba imporre vincoli aggiuntivi alle specifiche unique_ptr, solo per evitare un possibile uso improprio.

Ci sono ancora casi d'uso valide per mantenere il rvalue unique_ptr dereferenceable?

La durata di un temporaneo termina alla fine di un'espressione completa di cui fa parte il temporaneo.Ciò significa che l'oggetto ottenuto da un dereferencing unique_ptr è valido fino a quando l'associato unique_ptr è vivo, in modo che i sottostanti casi d'uso sono validi, e non sarebbe possibile se operator* è stato disattivato per rvalues:

(*f()).foo(); 
//   ^~~ unique_ptr is destroyed here 


use(*f()); 
//  ^~~ unique_ptr is destroyed here 
Problemi correlati