Pregunta Nullptr y verificar si un puntero apunta a un objeto válido


En algunos de mis viejos proyectos de código, 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 hacía algo como esto ...

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

O cuando necesitaba eliminar el objeto de forma segura, algo como esto

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

Bueno, ahora he aprendido acerca de los problemas que pueden surgir al usar objetos y punteros en expresiones booleanas, tanto 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 nullptr palabra clave. Pero ahora tengo curiosidad.

Ya revisé y revisé la mayor parte de mi código para que, por ejemplo, al eliminar objetos ahora escriba

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

Ahora me pregunto por el booleano. Cuando pase solo diga un int en una declaración if como esta,

int meh;
if(meh)

Luego verifica implícitamente cero sin necesidad de 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.


32
2017-07-01 05:00


origen


Respuestas:


En C, cualquier cosa que no sea 0 es verdadera. Entonces, ciertamente puedes usar:

if (ptrToObject) 
    ptrToObject->doSomething();

para eliminar de forma segura los punteros.

C ++ 11 cambia el juego un poco, nullptr_t es un tipo de cual nullptr es una instancia; la representación de nullptr_t es específico de la implementación Entonces un compilador puede definir nullptr_t como quiera Solo necesita asegurarse de que pueda imponer la restricción adecuada en el lanzamiento de un nullptr_t a diferentes tipos, de los cuales booleano está permitido, y asegúrese de que puede distinguir entre nullptr_t y 0.

Asi que nullptr será debidamente e implícitamente lanzado a la booleano  false siempre que el compilador siga 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);

Debido a cuánto tiempo he estado escribiendo estos ifs de esta manera, en este punto es una segunda naturaleza verificar si los punteros son válidos antes de usar escribiendo (objeto *) y luego llamando a sus miembros.

No. Mantenga un gráfico adecuado de los objetos (preferiblemente utilizando 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.


34
2017-07-01 05:08



No es posible probar 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 sin formato, 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 a nullptr .


8
2017-09-08 00:25