Esistono diverse difficoltà con i puntatori:
- Aliasing La possibilità di modificare il valore di un oggetto utilizzando nomi / variabili diversi.
- Non località La possibilità di modificare un valore di oggetti in un contesto diverso da quello in cui viene dichiarato (ciò accade anche con argomenti passati per riferimento).
- Mancata corrispondenza della durata La durata di un puntatore potrebbe essere diversa dalla durata dell'oggetto a cui punta e ciò potrebbe portare a riferimenti non validi (SEGFAULTS) o immondizia.
- Puntatore aritmetico . Alcuni linguaggi di programmazione consentono la manipolazione di puntatori come numeri interi e ciò significa che i puntatori possono puntare ovunque (compresi i punti più imprevisti quando è presente un bug). Per usare correttamente l'aritmetica del puntatore, un programmatore deve essere consapevole delle dimensioni della memoria degli oggetti indicati e questo è qualcosa in più a cui pensare.
- Cast di tipi La possibilità di lanciare un puntatore da un tipo a un altro consente di sovrascrivere la memoria di un oggetto diverso da quello previsto.
Ecco perché un programmatore deve pensare in modo più approfondito quando utilizza i puntatori (non conosco i due livelli di astrazione ). Questo è un esempio dei tipici errori commessi da un principiante:
Pair* make_pair(int a, int b)
{
Pair p;
p.a = a;
p.b = b;
return &p;
}
Si noti che codice come quello sopra è perfettamente ragionevole in linguaggi che non hanno un concetto di puntatori ma piuttosto uno di nomi (riferimenti), oggetti e valori, come fanno i linguaggi di programmazione funzionale e i linguaggi con Garbage Collection (Java, Python) .
La difficoltà con le funzioni ricorsive si verifica quando le persone senza sufficiente background matematico (in cui la ricorsività è comune e conoscenza richiesta) cercano di avvicinarsi a loro pensando che la funzione si comporterà in modo diverso a seconda di quante volte è stata chiamata in precedenza . Questo problema è aggravato perché le funzioni ricorsive possono davvero essere create in modi in cui devi pensare in quel modo per capirle.
Pensa alle funzioni ricorsive con i puntatori passati, come in un'implementazione procedurale di un albero rosso-nero in cui la struttura dei dati viene modificata sul posto; è qualcosa di più difficile da pensare rispetto a una controparte funzionale .
Non è menzionato nella domanda, ma l'altro importante problema con cui i principianti hanno difficoltà è la concorrenza .
Come altri hanno già detto, esiste un ulteriore problema non concettuale con alcuni costrutti del linguaggio di programmazione: è anche se capiamo che errori semplici e onesti con tali costrutti possono essere estremamente difficili da debug.