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.
Vorrei correggere la mia domanda: Con il termine "funzione membro" nella mia seconda domanda, voglio dire "funzione di membro static" – SlowAndSteady