2010-06-30 8 views
20

El título prácticamente resume mi pregunta. ¿Por qué no se puede hacer lo siguiente para buscar un puntero nulo?¿Por qué auto_ptr <T> tiene operador!() Definido?

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

Esto se debe hacer en su lugar:

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

Por qué no auto_ptr<T> simplemente han definido operator!()?

+0

La pregunta http://stackoverflow.com/q/2953530/427532 está relacionada de alguna manera. –

Respuesta

19

Parece que hubo un error en su diseño. Esto se solucionará en C++ 0x. unique_ptr (reemplazo para auto_ptr) contiene explicit operator bool() const;

Presupuesto de nuevo C++ estándar:

está en desuso El auto_ptr plantilla de clase. [Nota: La plantilla de clase unique_ptr (20.9.10) proporciona una mejor solución . nota -fin]


algunas aclaraciones:
Q: ¿Qué hay de malo en a.get() == 0?
A: No hay nada incorrecto en a.get()==0, pero los punteros inteligentes le permiten trabajar con ellos, ya que son punteros reales. Adicional operator bool() le da esa opción. Creo que la verdadera razón para hacer que auto_ptr sea obsoleto es que tiene un diseño no intuitivo. Pero operator bool para unique_ptr en el nuevo estándar significa que no hay razones para no tenerlo.

+0

Pregunta "estúpida": ¿qué significa 'explicit' aquí? Solo lo he visto con constructores. –

+3

Significa lo mismo que significa para los constructores: que el constructor o el operador de conversión no participe en el baile de conversión implícita que ocurre cuando intentas pasar un objeto a una función esperando una arg de un tipo diferente –

+0

Sure, 'auto_ptr 'ha quedado en desuso, pero ¿por qué fue un error de diseño no tener' operator!() '? ¿Qué pasa con 'a.get() == 0'? –

8

En pocas palabras, debe tener operator !() definido. auto_ptr no es un contenedor muy bien diseñado. Los punteros inteligentes en boost tienen definido el operador de conversión operator bool() que puede negarse con operator !(). Eso permitirá que su if(!p) compile y funcione como se espera.

+9

"' auto_ptr' no es un contenedor muy bien diseñado "lo resume muy bien. – Cogwheel

+3

'auto_ptr' no es un contenedor. Además, ¿por qué debería tener 'operator!()' Defined? Si va a reclamar esto, entonces creo que necesita justificar este reclamo. No puedo ver ninguna razón inherente para definirlo; no es como 'if (a.get() == 0)' no está claro o es difícil de usar. –

+3

Si algo está diseñado para actuar como un puntero más inteligente, entonces sus interfaces deben parecerse a un puntero. – Cogwheel

0

Sospecho porque se esperaba que pasar por auto_ptr s a nulo sería un caso raro, para evitar agregar una interfaz adicional, y para hacerlo explícito cuando realmente se busca nulo.

+0

Dado que auto_ptr :: operator = transfiere la propiedad y establece el origen auto_ptr en nulo, auto_ptr a null puede ser bastante común. –

4

Hay un problema con la conversión booleana. Permite sintaxis que casi siempre son un dolor.

Hay, afortunadamente, una solución: el idioma Safe Bool.

El problema con una conversión a bool es que la conversión implícita es peligrosa.

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

if (p < q) // uh ? 

Por lo tanto, operator bool() const es una abominación. O bien, proporciona un método explícito ... o usa la expresión idiomática de bool seguro.

La idea del modismo es darte una instancia de un tipo con un subconjunto de operaciones bastante mínimo y casi ningún caso en el que la conversión implícita te meta en problemas. Esto se hace usando un puntero a la función miembro.

Las operaciones como if (p) y if (!p) tienen sentido, pero if (p < q) no se compilará.

Lea atentamente el enlace para ver la solución completa, y se dará cuenta de por qué fue una buena idea no tener operator bool() const.

Cuestiones relacionadas