2011-07-16 32 views
12
int& fun() 
{ 
    int * temp = NULL; 
    return *temp; 
} 

En el método anterior, estoy tratando de desreferenciar un puntero NULL. Cuando llamo a esta función, no da excepción. Encontré que cuando el tipo de devolución es por referencia, no da una excepción si es por valor y luego lo hace. Incluso cuando la eliminación de referencia del puntero NULL se asigna a la referencia (como la línea siguiente), tampoco da.Asignación de una referencia desreferenciando un puntero NULL

int* temp = NULL: 
int& temp1 = *temp; 

Aquí mi pregunta es que el compilador no hace la desreferenciación en caso de referencia?

+4

Las referencias se manejan como apuntadores internamente, solo que son diferentes en la sintaxis que se usa en ellas. Sabiendo que su desreferenciación solo "asigna" el valor del puntero a la referencia, lo que hace referencia a NULL. Eso no dispara ningún acceso a la memoria. Cuando regrese por valor, la desreferenciación dará como resultado un acceso a la memoria en 0, que casi siempre le da una segfault. – Nobody

+0

Consulte este artículo, que explica por qué el puntero NULL es una característica terrible en OOP y debe evitarse a toda costa: http://www.yegor256.com/2014/05/13/why-null-is-bad.html – yegor256

Respuesta

16

Desreferenciando un puntero nulo es Comportamiento indefinido.

Un comportamiento indefinido significa que cualquier cosa puede pasar, por lo que no es posible definir un comportamiento para esto.

Es cierto que voy a agregar esta cita estándar de C++ por enésima vez, pero parece que tiene que ser así.

con respecto al comportamiento Indefinido,

C++ estándar sección 1.3.24 estados:

comportamiento indefinido admisible varía de ignorar la situación completamente con resultados imprevisibles, a comportarse durante la traducción o la ejecución del programa en una manera documentada característica del entorno (con o sin la emisión de un mensaje de diagnóstico), para terminar una traducción o ejecución (con la emisión de un mensaje de diagnóstico).

NOTA:
Además, sólo para llevarla a su notificación:
Usando una referencia devuelta o puntero a una variable local dentro de una función es también un comportamiento indefinido. Debería asignar el puntero en freestore (heap) usando new y luego devolverle una referencia/puntero.

EDIT:
Como McNellis @ James, señala apropiadamente en los comentarios,
Si no se usa el puntero o referencia devuelta, el comportamiento es bien definido.

+0

Sí, acuerde el UB mencionado anteriormente. pero mi pregunta es si la desreferenciación del puntero NULL o del puntero NULL se realiza para asignar eso a una referencia, ¿entonces el compilador realiza la operación de desreferenciación? como- Int * t = NULL; Int & t1 = * t; –

+1

@G Mann: Reference es solo un 'alias' del tipo original en el que se inicializó. Cómo se implementa es un detalle de implementación de compiladores y el estándar no define cómo se debe implementar. –

+2

Cuando respeta un puntero nulo, el código no es válido y el compilador puede hacer cualquier cosa. No tiene sentido preguntar * por qué * hizo algo. –

7

Cuando desreferencia un puntero nulo, no necesariamente obtiene una excepción; todo lo que está garantizado es que el comportamiento no está definido (lo que realmente significa que no hay garantía en absoluto sobre cuál es el comportamiento).

Una vez que se evalúa la expresión *temp, es imposible razonar sobre el comportamiento del programa.

+0

Estoy agregando el mismo comentario que hice en otra publicación. Sí, estoy de acuerdo con el UB mencionado anteriormente. pero mi pregunta es si la desreferenciación del puntero NULL o del puntero NULL se realiza para asignar eso a una referencia, ¿entonces el compilador realiza la operación de desreferenciación? como- Int * t = NULL; Int & t1 = * t; –

+0

Es el caso que para la mayoría de los compiladores, en muchas circunstancias, se implementa una referencia como un puntero. Más allá de eso, depende del compilador, la configuración, etc. –

+0

Corrígeme que estoy equivocado. Donde se implementa como puntero, entonces el compilador puede no estar haciendo la operación de desreferenciación. –

0

yo no estoy seguro de entender lo que está tratando de tareas. La desreferencia del puntero ** NULL ** no está definida.

En caso de que quiera para indicar que el método no siempre devuelve el valor se puede declarar como:

diversión bool (int & val);

o forma STL (similar a std :: mapa de inserción):

std::pair<int, bool> fun(); 

o realce manera:

boost::optional<int> fun(); 
4

Estás no permitido eliminar referencia a un puntero nulo, por lo el compilador puede generar código asumiendo que no haces eso. Si lo haces de todos modos, el compilador puede ser agradable y decirte, pero no tiene por qué hacerlo. Es su parte del contrato que dice que no debe hacerlo.

En este caso, apuesto a que el compilador será sea agradable y le diga el problema ya en tiempo de compilación, si solo establece el nivel de advertencia correctamente.

Cuestiones relacionadas