Recursivitate: return și cout nu fac același lucru
Urmărește separat valoarea returnată și textul afișat de o funcție recursivă. Compară afișarea înainte și după apel și verifică cazul de bază.
În acest material
O funcție poate afișa un număr fără să îl returneze și poate returna un număr fără să afișeze nimic. În recursivitate, confundarea acestor două efecte face dificilă urmărirea apelurilor și duce la răspunsuri greșite chiar pentru exemple foarte mici.
Două întrebări pentru fiecare apel
Ce valoare primește apelantul? Ce text a fost trimis la ieșire în timpul apelului? return încheie apelul curent și, într-o funcție cu rezultat, furnizează valoarea corespunzătoare. cout produce afișare, iar execuția continuă cu instrucțiunea următoare.
Dacă funcția întoarce n plus rezultatul unui apel mai mic, adunarea are loc după revenirea acelui apel. Dacă înaintea lui există o afișare a lui n, textul poate apărea înainte ca valoarea întoarsă să fie cunoscută.
Pentru apelul cu n=3, afișarea înaintea recursiei produce 3,2,1; afișarea după recursie produce 1,2,3.Mărește schema ↗
Afișare înainte de apel
Consideră descrierea: dacă n este zero, oprește apelul; altfel afișează n și apelează aceeași funcție pentru n-1. Pentru n=3, afișarea este 3, 2, 1. La fiecare nivel, afișarea se produce înainte de coborâre.
Scrie trei rânduri separate pentru apelurile cu 3, 2 și 1. Apelul cu zero nu afișează nimic. Nu număra cazul de bază drept o afișare dacă instrucțiunea de oprire apare înaintea lui cout.
Afișare după apel
Mută afișarea după apelul pentru n-1, păstrând același caz de bază. Pentru n=3, cobori până la zero fără afișare. La revenire, apelul cu 1 afișează primul, apoi cel cu 2 și cel cu 3. Rezultatul este 1, 2, 3.
Valorile parametrului nu se transformă toate în zero. Fiecare apel are propria valoare locală a lui n. La revenire, apelul cu 3 continuă cu n=3. Aceasta este ideea pe care trebuie să o fixeze desenul stivei de apeluri.
Returnarea nu se propagă singură
Dacă apelezi o funcție care produce un rezultat, dar ignori acel rezultat, apelantul nu îl primește automat. Pentru o funcție cu tip de întoarcere diferit de void, traseele relevante trebuie să furnizeze rezultatul cerut. Scrierea unei expresii de apel nu este echivalentă cu returnarea valorii ei.
La factorial, de exemplu, rezultatul apelului mai mic participă la o înmulțire. Verifică separat domeniul numeric: chiar o recursie logic corectă poate depăși capacitatea tipului pentru n prea mare.
Cum alegi testele
Testează cazul de bază, apoi un apel aflat la un pas de el și un exemplu cu trei niveluri. Pentru fiecare, notează ordinea afișărilor și rezultatul întors în coloane diferite. Dacă funcția are două apeluri recursive, păstrează și ordinea în care ele sunt evaluate conform instrucțiunilor programului.
Nu concluziona că recursivitatea are memorie constantă doar pentru că nu declară un vector. Apelurile active ocupă stiva. Într-un lanț de n apeluri, adâncimea poate crește liniar.
Recapitulează apelul și return, stiva apelurilor recursive și combinarea rezultatelor în divide et impera.
Întrebări frecvente
Care este diferența dintre return și cout într-o funcție?
return încheie apelul curent și poate transmite o valoare apelantului. cout scrie text la ieșire, apoi execuția continuă. O valoare afișată nu este automat și valoarea returnată.
De ce se schimbă ordinea afișării în recursivitate?
O afișare înaintea apelului recursiv are loc la coborârea în apeluri. O afișare după el se execută la revenire, când apelul mai adânc s-a terminat.
Return oprește toate apelurile recursive?
Nu. Oprește numai apelul curent. Controlul revine în apelant, care continuă după locul apelului și își execută propriile instrucțiuni rămase.