Il y a plusieurs difficultés avec les pointeurs:
- Aliasing La possibilité de changer la valeur d'un objet en utilisant différents noms / variables.
- Non-localité La possibilité de changer la valeur d'un objet dans un contexte différent de celui dans lequel il est déclaré (cela se produit également avec des arguments passés par référence).
- Incohérence de durée de vie La durée de vie d'un pointeur peut être différente de la durée de vie de l'objet vers lequel il pointe, ce qui peut entraîner des références non valides (SEGFAULTS) ou des ordures.
- Arithmétique des pointeurs . Certains langages de programmation permettent la manipulation de pointeurs sous forme d'entiers, ce qui signifie que les pointeurs peuvent pointer n'importe où (y compris les endroits les plus inattendus lorsqu'un bogue est présent). Pour utiliser correctement l'arithmétique des pointeurs, un programmeur doit être conscient de la taille de la mémoire des objets pointés, et c'est quelque chose de plus à penser.
- Conversion de type La possibilité de convertir un pointeur d'un type à un autre permet d'écraser la mémoire d'un objet différent de celui prévu.
C'est pourquoi un programmeur doit réfléchir plus à fond lorsqu'il utilise des pointeurs (je ne connais pas les deux niveaux d'abstraction ). Voici un exemple des erreurs typiques commises par un novice:
Pair* make_pair(int a, int b)
{
Pair p;
p.a = a;
p.b = b;
return &p;
}
Notez que le code comme ci-dessus est parfaitement raisonnable dans les langages qui n'ont pas de concept de pointeurs mais plutôt de noms (références), d'objets et de valeurs, comme le font les langages de programmation fonctionnels et les langages avec garbage collection (Java, Python). .
La difficulté avec les fonctions récursives se produit lorsque des personnes sans formation mathématique suffisante (où la récursivité est courante et requiert des connaissances) essaient de les approcher en pensant que la fonction se comportera différemment selon le nombre de fois où elle a été appelée auparavant . Ce problème est aggravé parce que les fonctions récursives peuvent en effet être créées de manière à ce que vous ayez à penser de cette façon pour les comprendre.
Pensez à des fonctions récursives avec des pointeurs transmis, comme dans une implémentation procédurale d'un arbre rouge-noir dans lequel la structure de données est modifiée sur place; c'est quelque chose de plus difficile à penser qu'une contrepartie fonctionnelle .
Ce n'est pas mentionné dans la question, mais l'autre problème important avec lequel les novices ont des difficultés est la concurrence .
Comme d'autres l'ont mentionné, il existe un problème supplémentaire, non conceptuel, avec certaines constructions de langage de programmation: c'est que même si nous comprenons, des erreurs simples et honnêtes avec ces constructions peuvent être extrêmement difficiles à déboguer.