2010-08-04 17 views
7

sigo siendo un novato C++. Acabo de leer que la función de miembro estático de una clase no es específica del objeto; hay una sola copia de las funciones miembro para todos los objetos.asignación de memoria para las funciones en C++

Ahora surgen dos preguntas en mi mente:

  1. ¿Cuál es la diferencia entre una función ordinaria y una función estática "en términos de asignación de memoria única"?

  2. ¿Qué sucede si la función miembro contiene algunas variables locales? En ese caso, la función "debería" tener una copia separada de esa variable, específica para el objeto que invoca la función ... ¿Cómo se resuelve este problema en C++?

Gracias!

+0

me gustaría corregir mi pregunta: ¿Por "función miembro" en mi segunda pregunta, me refiero a "función miembro estática" – SlowAndSteady

Respuesta

9

¿Cuál es la diferencia entre una función ordinaria y una función estática "en términos de asignación de memoria único"?

Nada. Una función estática es como una función global, excepto por el alcance.

Incluso para funciones de miembros no estáticos, no se requiere memoria extra. La función de miembro int C::f(int arg1, int arg2) es solo azúcar sintáctica para algo como int C__f(C* this, int arg1, int arg2).

¿Qué sucede si la función miembro contiene algunas variables locales? En ese caso la función "debe" tener una copia separada de esa variable - específica a el objeto invocando la función ...

Hay una copia de las variables locales para cada invocación de la función (a menos que sean static). Esta es la razón por la recursión posible en C++.

¿Cómo se resuelve este problema en C++?

Las llamadas a funciones se basan en "marcos de pila". Un marco de pila consta de:

  • Los argumentos para la función (incluido el implícito this si corresponde).
  • Cualquier otra variable local que no sea static en la función.
  • La "dirección de retorno", que le dice al procesador dónde reanudar la ejecución una vez que se realiza la función.

Cada vez que se invoca una función, se crea un marco de pila. Cuando la función es, el marco de pila se destruye. Si se llama a una función recursivamente, cada nivel de recursión obtiene su propio marco de pila. Por ejemplo, si usted tiene

int factorial(int n) { 
    if (n <= 1) 
     return 1; 
    else 
     return factorial(n - 1) * n; 
} 

Entonces, cuando usted llame factorial(3), un marco de pila se crea de este modo:

------------------------ stack pointer (SP) 
n = 3 
RA = <in main()> 

Cuando se hace la llamada recursiva a factorial(2), se añade una trama adicional al parte superior de la pila

------------------------ SP 
n = 2 
RA = <in factorial()> 
------------------------ 
n = 3 
RA = <in main()> 

Otra llamada recursiva se hace, a factorial(1).

------------------------ SP 
n = 1 
RA = <in factorial()> 
------------------------ 
n = 2 
RA = <in factorial()> 
------------------------ 
n = 3 
RA = <in main()> 

Este es el caso base para la recursión, y el valor de retorno de 1 se almacena en un registro. La llamada a la función se ha completado, el marco de la pila superior se destruye y la ejecución continúa en la dirección de retorno guardada.

------------------------ SP 
n = 2          
RA = <in factorial()> 
------------------------ 
n = 3 
RA = <in main()> 

Ahora, la llamada a factorial(2) puede calcular su valor de retorno (2), y otro marco de pila puede ser destruido:

------------------------ SP 
n = 3 
RA = <in main()> 

Finalmente, podemos calcular el resultado de la llamada función original (6), y destruir este marco de pila también.

+0

Me gustaría corregir mi pregunta: por "función de miembro" en mi segunda pregunta, me refiero a "función de miembro estático" – SlowAndSteady

+0

Los marcos de pila funcionan de la misma manera para funciones de miembro estáticas y no estáticas. La única diferencia es si 'this' es una de las variables locales. – dan04

4
  1. ninguna diferencia
  2. variables locales se crean y se destruyen en la pila por invocación de la función
+0

Si la función en sí tiene sólo 1 copia, ¿cómo puede tener múltiples copias de sus variables en la pila? – SlowAndSteady

+5

Hay un marco de pila para cada INVOCACIÓN de la función. – dan04

2
  1. Me parecería muy poco probable que no habría una diferencia

  2. Parece que debería leer un poco sobre la diferencia entre montón y asignaciones de pila. Esto da una buena idea sobre cómo funciona la memoria a un nivel bajo, pero aún alto. Lo siento, no puedo ser más útil ahora mismo.

edición: demasiado lento :)

0
  1. Realmente no hay mucha diferencia. Ambos se almacenan en la memoria solo una vez, cuando se llama a un método no estático, se inserta un puntero al objeto actual (este puntero) en la pila (o se almacena en ECX dependiendo de su compilador) además de todas las funciones parámetros. Una función estática no necesita una instancia de una clase, por lo que simplemente se llama como una función C normal.

  2. Igual que en C, con la pila de llamadas.

Cuestiones relacionadas