2010-08-04 27 views
7

Sono ancora un principiante C++. È appena arrivato a leggere che la funzione membro statico di una classe non è specifica dell'oggetto - esiste una singola copia delle funzioni membro per tutti gli oggetti.Allocazione memoria alle funzioni in C++

Ora due domande sorgono nella mia mente:

  1. Qual è la differenza tra una funzione ordinaria e una funzione statica "in termini di allocazione di memoria solo"?

  2. Cosa succede se la funzione membro contiene alcune variabili locali? In tal caso, la funzione "dovrebbe" avere una copia separata di quella variabile, specifica per l'oggetto che richiama la funzione ... Come si risolve questo problema in C++?

Grazie!

+0

Vorrei correggere la mia domanda: Con il termine "funzione membro" nella mia seconda domanda, voglio dire "funzione di membro static" – SlowAndSteady

risposta

9

Qual è la differenza tra un funzione ordinaria e uno statico funzione "in termini di memoria allocazione solo"?

Niente. Una funzione statica è proprio come una funzione globale ad eccezione dell'ambito.

Anche per le funzioni membro non statiche, non è richiesta memoria aggiuntiva. La funzione membro int C::f(int arg1, int arg2) è solo zucchero sintattico per qualcosa come int C__f(C* this, int arg1, int arg2).

Cosa succede se la funzione membro contiene alcune variabili locali? In tal caso la funzione "dovrebbe" avere una copia separata di quella variabile - specifico per all'oggetto invocando la funzione ...

C'è una copia delle variabili locali per ogni invocazione della funzione (a meno che non siano static). Questo è il motivo per cui la ricorsione è possibile in C++.

Come viene risolto questo problema in C++?

Le chiamate di funzione sono basate su "frame di stack". Un frame stack è composto da:

  • Gli argomenti della funzione (incluso l'implicito this se applicabile).
  • Eventuali altre variabili locali non static nella funzione.
  • "indirizzo di ritorno", che indica al processore dove riprendere l'esecuzione una volta terminata la funzione.

Ogni volta che viene chiamata una funzione, viene creato un frame di stack. Quando la funzione è, il frame dello stack viene distrutto. Se una funzione è chiamata in modo ricorsivo, ciascun livello di ricorsione ottiene il proprio frame dello stack. Ad esempio, se si dispone di

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

Poi, quando si chiama factorial(3), uno stack frame viene creato in questo modo:

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

Quando la chiamata ricorsiva è fatto per factorial(2), un telaio supplementare è aggiunto alla cima alla pila

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

Un'altra chiamata ricorsiva è fatto, per factorial(1).

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

Questo è il caso base per la ricorsione, e il valore di ritorno di 1 è memorizzato in un registro. La chiamata alla funzione è completa, il frame dello stack superiore viene distrutto e l'esecuzione continua con l'indirizzo di ritorno salvato.

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

Ora, la chiamata a factorial(2) può calcolare il suo valore di ritorno (2), e un altro frame stack può essere distrutto:

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

Infine, possiamo calcolare il risultato della chiamata funzione originale (6), e distruggi anche questo stack frame.

+0

Vorrei correggere la mia domanda: Con il termine "funzione membro" nella mia seconda domanda, voglio dire "funzione di membro static" – SlowAndSteady

+0

stack frame funzionano allo stesso modo per le funzioni di membro statici e non statici. L'unica differenza è se "questo" è una delle variabili locali. – dan04

4
  1. alcuna differenza
  2. variabili locali vengono creati e distrutti nello stack per ogni invocazione della funzione
+0

Se la funzione in sé ha solo 1 copia, come può avere più copie di sue variabili in pila? – SlowAndSteady

+5

C'è una cornice di stack per ogni INVOCAZIONE della funzione. – dan04

2
  1. avrei trovato molto improbabile che ci sarebbe una differenza

  2. Sembra che dovresti leggere un po 'sulla differenza tra heap e allocazioni stack. Questo dà una buona idea di come la memoria funzioni a un livello basso, ma comunque di alto livello. Scusa, non posso essere più utile in questo momento.

edit: troppo lento :)

0
  1. Non c'è davvero molta differenza. Entrambi sono archiviati in memoria una sola volta, quando viene chiamato un metodo non statico, un puntatore all'oggetto corrente (il puntatore this) viene inserito nello stack (o memorizzato in ECX a seconda del compilatore) in aggiunta a tutte le funzioni della funzione parametri. Una funzione statica non ha bisogno di un'istanza di una classe, quindi viene chiamata semplicemente come una normale funzione C.

  2. stesso modo che in C, con lo stack di chiamate.