2012-07-01 7 views
30

En un par de mis proyectos de código anteriores cuando nunca había oído hablar de punteros inteligentes, cada vez que tenía que comprobar si el puntero aún apuntaba a un objeto válido, siempre lo hacía algo como esto ...Nullptr y comprobar si un puntero apunta a un objeto válido

object * meh = new object; 
if(meh) 
    meh->member; 

O cuando necesitaba para eliminar el objeto con seguridad, algo como esto

if(meh) 
{ 
    delete meh; 
    meh = 0; 
} 

Bueno, ahora he aprendido acerca de los problemas que pueden surgir del uso de objetos y punteros en expresiones booleanas ambas con números literales, de la manera difícil:. Y ahora también he aprendido de la característica no tan nueva pero genial de C++, la palabra clave nullptr. Pero ahora tengo curiosidad.

que ya han pasado por y revisado la mayor parte de mi código de manera que, por ejemplo, al eliminar objetos que ahora escribo

if(meh) 
{ 
    delete meh; 
    meh = nullptr; 
} 

Ahora me pregunto sobre el booleano. Cuando se pasa simplemente decir un int en una sentencia if como esta,

int meh; 
if(meh) 

Entonces implícitamente cheques por cero sin necesidad de que escribirlo.

if(meh == 0) // does the exact same check 

Ahora, ¿C++ hará lo mismo con los punteros? Si pasa un char * como este a una declaración if?

char * meh; 
if(meh) 

¿Entonces lo comparará implícitamente con nullptr? Debido a cuánto tiempo he estado escribiendo estos ifs de esta manera, en este momento es una segunda naturaleza verificar si los punteros son válidos antes de usar escribiendo (objeto *) y luego llamando a sus miembros. Si esta no es la funcionalidad, ¿por qué no? Demasiado difícil de implementar? Resolvería algunos problemas al eliminar otra forma más pequeña de desordenar tu código.

+22

No ** necesita ** punteros de ckeck antes de 'borrar'. Es completamente seguro 'eliminar' un' nullptr'. –

+1

En su último ejemplo, ¿quiso decir 'char * meh = nullptr; si (meh) '? El puntero no está inicializado. –

+3

El resultado de su expresión 'new' nunca será nulo, en su lugar se usan excepciones. Como se mencionó, eliminar null está bien, no hace nada. Además, generalmente es mejor no restablecer el valor de un puntero a nulo. La última vez que se utiliza debe ser la última vez que no es nulo, por lo que tener acceso a un puntero eliminado se debe considerar un error; establecerlo en null oculta eso. – GManNickG

Respuesta

32

En C, cualquier cosa que no sea 0 es verdadera. Por lo tanto, ciertamente puede usar:

if (ptrToObject) 
    ptrToObject->doSomething(); 

para desviar de forma segura los punteros.

C++ 11 cambia un poco el juego, nullptr_t es un tipo del cual nullptr es una instancia; la representación de nullptr_t es específica de la implementación. Entonces un compilador puede definir nullptr_t como quiera. Sólo es preciso asegurarse de que puede cumplir la restricción adecuada en la colada de una nullptr_t a diferentes tipos - de los cuales se permite booleano - y asegúrese de que puede distinguir entre un nullptr_t y 0.

Así nullptr habrá e emitir de manera implícita y correcta al booleanfalse siempre que el compilador cumpla con la especificación del lenguaje C++ 11. Y el fragmento de arriba todavía funciona.

Si elimina un objeto al que se hace referencia, nada cambia.

delete ptrToObject; 
assert(ptrToObject); 
ptrToObject = nullptr; 
assert(!ptrToObject); 

Por cuánto tiempo he estado escribiendo estos IFS como este, es una segunda naturaleza en este punto para comprobar si los punteros válidos antes de usar escribiendo si (objeto *) y luego llamar Sus miembros.

No. Por favor mantienen un gráfico adecuado de objetos (preferiblemente el uso de punteros únicos/inteligentes). Como se señaló, no hay manera de determinar si un puntero que no es nullptr apunta a un objeto válido o no. La responsabilidad recae en usted para mantener el ciclo de vida de todos modos ... esta es la razón por la que existen las envolturas del puntero en primer lugar.

+0

bueno, ya lo sabía. cuando se deja sin una comparación, si las declaraciones comprueban si lo que se pasa resuelve literalmente cualquier cosa menos 0. si int meh = 0, entonces resuelve falso. sin embargo, si la dirección de decir un int * es 0x000, etc. lo que significa que no apunta a nada y el bool resolverá falso. si apunta a algún lugar, entonces no es cero y luego se resuelve verdadero. pero, ¿y si eliminas el objeto en el puntero? el stil ptr contiene la dirección como 0x81A3 o algo así, pero el objeto se ha ido. llama al if y se resuelve verdadero, aunque no haya un objeto allí. – FatalCatharsis

+1

que causaría un error de tiempo de ejecución, si olvidó poner a cero el puntero. pero si el puntero se comparaba implícitamente con nullptr, entonces si el puntero era 0 o se dirigía a algo, se resolvería como falso cuando el objeto no estaba allí. – FatalCatharsis

+2

Sí. Entonces, ¿cuál es tu pregunta? – dcow

6

No es posible comprobar si un puntero apunta a un objeto válido o no. Si el puntero no es nulo pero no apunta a un objeto válido, usar el puntero genera un comportamiento indefinido. Para evitar este tipo de error, le corresponde a usted tener cuidado con la vida útil de los objetos a los que se apunta; y las clases de punteros inteligentes ayudan con esta tarea.

Si meh es un puntero prima, entonces no hay diferencia alguna entre if (meh) y if (meh != 0) y if (meh != nullptr). Todos proceden si el puntero no es nulo.

Hay una conversión implícita del literal 0 al nullptr.

Cuestiones relacionadas