Istruzioni di Salto (Jump Statements) e goto
Le Jump Statements (Istruzioni di salto) sono costrutti non-condizionali che tranciano e deviano esplicitamente il Control Flow dell’esecuzione, senza tenere conto di logiche intermedie.
La programmazione C++ ad alto livello scoraggia il loro impiego fuori dai recinti ben limitati per via del disorientamento logico che causano. Abbiamo tre salti canonici.
L’istruzione break
Section titled “L’istruzione break”Lo statement break è un terminatore di blocco. Incontrarlo forza la macchina ad abbandonare immediatamente ed in modo definitivo lo switch o il ciclo iterativo (for, while) più vicino che lo contiene. Il ciclo smette di iterare.
Nel caso dei loop annidati (nested loops), il break distrugge unicamente l’esecuzione del ciclo in cui è stato evocato, e non interromperà il ciclo padre superiore.
L’istruzione continue
Section titled “L’istruzione continue”L’istruzione continue è un saltatore d’iterazione. Ordina l’immediata sospensione del codice rimanente del corpo del loop corrente, per procedere istantaneamente all’iterazione successiva (avviando i trigger di avanzamento, come l’incremento di indice o dell’iteratore).
Il loop rimarrà vivo.
Il Paria del C++: l’Operatore goto
Section titled “Il Paria del C++: l’Operatore goto”L’istruzione goto impone un salto incondizionato, istantaneo e cieco, verso una Label (un’etichetta) piazzata in qualsiasi punto della funzione attuale.
Le etichette (Labels) non hanno effetto di per sé, servono solo come meta di atterraggio e si dichiarano premettendo un identificatore ai due punti (nome_label:).
int main() { goto jedi; // Ignoro tutto e salto di sotto
printf("Io non saro' mai stampato.\\n");
jedi: printf("Che la forza sia con te.\\n"); return 0;}Qual è il ruolo del goto nel moderno C++? Nessuno. Va evitato severamente.
Permette di tessere logiche a tela di ragno (Spaghetti Code) che distruggono l’albero di esecuzione. Storicamente nel C (o nel programmare Kernel Linux) veniva utilizzato per saltare al punto finale di una funzione al fine di “pulire la memoria allocata e chiudere i socket di rete” in caso di errore, bypassando l’esecuzione lineare.
Nel C++ possediamo lo schema RAII (Resource Acquisition Is Initialization) coi suoi distruttori automatici allo spegnimento dei blocchi e i meccanismi di Eccezione (try/catch), rendendo l’obbrobrio sintattico del goto superfluo.