2010-06-30 23 views
20

Il titolo riassume abbastanza bene la mia domanda. Perché non è possibile fare quanto segue per verificare la presenza di un puntatore nullo?Perché auto_ptr <T> ha operatore!() Definito?

auto_ptr<char> p(some_expression); 
// ... 
if (!p) // error 

Questo deve essere fatto, invece:

if (!p.get()) // OK 

Perché non auto_ptr<T> semplicemente hanno operator!() definito?

+0

La domanda http://stackoverflow.com/q/2953530/427532 è in qualche modo correlata. –

risposta

19

Sembra che ci sia stato un errore nel suo design. Questo sarà risolto in C++ 0x. unique_ptr (sostituzione per auto_ptr) contiene explicit operator bool() const;

Citazione di nuovo C++ standard:

Il modello di classe auto_ptr è deprecato. [Nota: il modello di classe unique_ptr (20.9.10) fornisce una soluzione migliore . -end nota]


Alcuni chiarimenti:
D: Cosa c'è di sbagliato con a.get() == 0?
A: Non c'è niente che non va con a.get()==0, ma i puntatori intelligenti consentono di lavorare con loro come se fossero veri e propri indicatori. L'ulteriore operator bool() ti offre una tale scelta. Penso che la vera ragione per cui è stato reso deprecato auto_ptr è che non ha un design intuitivo. Ma operator bool per unique_ptr nel nuovo Standard significa che non ci sono ragioni per non averlo.

+0

Domanda "stupida": cosa significa "esplicito" qui? L'ho sempre visto solo con i costruttori. –

+3

Significa la stessa cosa che significa per i costruttori - che il costruttore o l'operatore di conversione non partecipa alla danza di conversione implicita che si verifica quando si tenta di passare un oggetto a una funzione che si aspetta un arg di un tipo diverso –

+0

Sicuro, 'auto_ptr 'è stato deprecato ma perché è stato un errore di progettazione non avere l'operatore!()'? Cosa c'è di sbagliato con 'a.get() == 0'? –

8

In poche parole, dovrebbe essere definito operator !(). auto_ptr non è un contenitore molto ben progettato. I puntatori intelligenti in boost hanno definito l'operatore di conversione operator bool() che può essere annullato con operator !(). Ciò consentirà al tuo if(!p) di compilare e funzionare come previsto.

+9

"auto_ptr' non è un contenitore molto ben progettato" lo riassume molto bene. – Cogwheel

+3

'auto_ptr' non è un contenitore. Anche perché dovrebbe avere l'operatore!() 'Definito? Se hai intenzione di reclamare questo, allora penso che tu debba giustificare questa affermazione. Non riesco a vedere alcun motivo intrinseco per definirlo; non è come se "if (a.get() == 0)" non sia chiaro o difficile da usare. –

+3

Se qualcosa è progettato per agire come un puntatore più intelligente, le sue interfacce dovrebbero assomigliare a un puntatore. – Cogwheel

0

Sospetto perché era prevedibile che il passaggio da auto_ptr a null sarebbe stato un caso raro, per evitare l'aggiunta di un'interfaccia aggiuntiva e renderlo esplicito quando si verifica effettivamente la presenza di null.

+0

Dato che auto_ptr :: operator = trasferisce la proprietà e imposta la sorgente auto_ptr su null, auto_ptr su null può essere abbastanza comune. –

4

C'è un problema con la conversione booleana. Permette sintassi che sono quasi sempre un dolore.

C'è, fortunatamente, una soluzione: l'idioma Safe Bool.

Il problema con una conversione in bool è che la conversione implicita è pericolosa.

std::auto_ptr<T> p = ..., q = ....; 

if (p < q) // uh ? 

Pertanto, operator bool() const è un abominio. O fornite un metodo esplicito ... o usate l'idioma di bool sicuro.

L'idea dell'idioma è di darti un'istanza di un tipo con un sottoinsieme di operazioni piuttosto minime e quasi nessun caso in cui la conversione implicita ti metterà nei guai. Questo viene fatto usando un puntatore alla funzione membro.

Operazioni come if (p) e if (!p) hanno senso, ma non sarà possibile compilare lo if (p < q).

Leggere attentamente il collegamento per la soluzione completa e capirete perché è stata una buona idea non avere operator bool() const.