Las referencias de C++ son alias. El efecto de esto es que las desreferencias a los indicadores no necesariamente ocurren donde aparecen, sino que ocurren donde se evalúan. Tomar una referencia a un objeto no evalúa el objeto, lo alía. Usar la referencia es lo que evalúa el objeto. C++ no puede garantizar que las referencias sean válidas; si lo hace, todos los compiladores de C++ están rotos. La única forma de hacerlo es eliminar toda posibilidad de asignación dinámica con referencias. En la práctica, la suposición es que una referencia es un objeto válido. Como * NULL no está definido & no válido, se deduce que para p = NULL, * p tampoco está definido. El problema con C++ es * p se pasará efectivamente a una función, o se retrasará en su evaluación hasta que la referencia se utilice realmente. Argumentar que no está definido no es el punto de la pregunta del que pregunta. Si fuera ilegal, el compilador lo haría cumplir, y también lo haría el estándar. Tampoco lo hace, de lo que estoy enterado.
int &r = *j; // aliases *j, but does not evaluate j
if(r > 0) // evaluates r ==> *j, resulting in dereference (evaluate j) at this line, not what some expect
;
1) Se puede probar una referencia para aliasing un puntero NULL, & r es simplemente & (cualquiera que sea r alias a) (EDIT)
2) Cuando se pasa un puntero "dereferenced" (* i) como un parámetro de referencia, la desreferencia no ocurre en el callsite, puede que nunca suceda, porque es una referencia (las referencias son alias, no evaluaciones). Esa es la optimización de las referencias. Si se evaluaron en el callsite, o bien el compilador está insertando código adicional, o sería una llamada por valor y menos rendimiento que un puntero.
Sí, la referencia en sí no es NULA, no es válida, del mismo modo que * NULL no es válido. Es la demora en la evaluación de las expresiones de desreferencia que no concuerda con la afirmación de que es imposible tener una referencia inválida.
#include <iostream>
int fun(int & i) {
std::cerr << &i << "\n";
std::cerr << i << "\n"; // crash here
}
int main() {
int * i = new int();
i = 0;
fun(*i); // Why not crash here? Because the deref doesn't happen here, inconsistent, but critical for performance of references
}
EDIT: cambió mi ejemplo, como se ha malinterpretado como sugerencia para referencias de pruebas, lo que no quería demostrar. Solo quería demostrar la referencia inválida.
Relacionados: http://stackoverflow.com/questions/1919608/checking-for-null-before-pointer- uso/1921403 # 1921403. –
"cómo sé que la memoria del objeto no se ha liberado/eliminado DESPUÉS de haber inicializado la referencia". ¿Cómo sabes que alguien no ha 'reinterpet_cast' algún objeto completamente incorrecto a tu tipo, y lo pasó como referencia? ¿O corrompió la memoria en su objeto y luego se la pasó a usted? No, en C y C++ te ves obligado a confiar en que tu interlocutor no será un muppet. Si hacen algo que el lenguaje define como no válido, como eliminar referencias de un puntero nulo o eliminar un objeto pero manteniendo una referencia al mismo, entonces ese es su error, y pueden depurarlo. –