c++ - funciones - punteros a cadenas
¿Qué sucederá cuando llame a una función miembro en un puntero de objeto NULL? (6)
El comportamiento más probable, en la mayoría de las computadoras modernas, es que se ejecutará e imprimirá "diversión" porque:
- C ++ no comprueba si el puntero es NULL antes de llamar a la función
-
fun()
no es virtual, por lo que no es necesario hacer referencia a un vtable para llamar afun()
-
fun()
nunca accede a ninguna variable miembro enA
por lo que no necesita desreferenciar el nulo dethis
puntero.
Me dieron lo siguiente como una pregunta de entrevista:
class A
{
public:
void fun()
{
std::cout << "fun" << std::endl;
}
};
A* a = NULL;
a->fun();
¿Qué sucederá cuando se ejecute este código y por qué?
Ver también:
Es un comportamiento indefinido, por lo que cualquier cosa puede pasar.
Un posible resultado sería que simplemente imprime "fun"
ya que el método no accede a las variables miembro del objeto al que se llama (no es necesario acceder a la memoria donde supuestamente vive el objeto, por lo que las violaciones de acceso no se realizan). necesariamente ocurre).
Lo he intentado varias veces, todo el tiempo la salida se vuelve "divertida", esto es porque la fun
función es independiente de la instancia a
. mientras llamas a->fun();
a
puntos a 0 por lo que este es un comportamiento indefinido, pero en la mayoría de los compiladores no debería producirse un bloqueo.
No podemos saber lo que será . Todo puede suceder, porque el programa expone el comportamiento indefinido. Consulte ¿La invocación de una función miembro en una instancia nula causa un comportamiento indefinido? .
Según el estándar, esto es un comportamiento indefinido y, por lo tanto, algo muy malo. En realidad, la mayoría de las plataformas de programación (tanto para X86 como para otras arquitecturas) funcionarán bien.
¿Por qué? Considere cómo se implementan las funciones de clase en C ++. Esta no es una función virtual, por lo tanto, esto puede ser una llamada estática a una dirección conocida. En el ensamblaje x86, podemos ver esto como
mov A, 0
mov ecx, A
call a__fun
ya que a__fun no requiere datos de instancia, aunque reciba un null este puntero, no pasará nada.
Todavía el código de mierda y cualquier compilador gritarán, pero se puede ejecutar.
Tres puntos pueden ayudar:
1) Todas las funciones se almacenan en el código o la sección de texto.
2) Las funciones no virtuales se resuelven al momento de cumplir.
3) Al llamar a las funciones miembro de la clase, pasamos el objeto actual como this
puntero a esa función.
Al llegar a su pregunta, aquí la función de fun()
ya está en la memoria (sección de código / sección de texto). Como función fun()
no es virtual, se resolverá en el momento de cumplimiento (es decir, para esta línea saltará a la instrucción X en la sección de código con this
puntero como NULL
). Como no se usa / llama ninguna función miembro ni función virtual en la función fun()
, funciona bien.