Hay varias dificultades con los punteros:
- Aliasing La posibilidad de cambiar el valor de un objeto usando diferentes nombres / variables.
- No localidad La posibilidad de cambiar el valor de un objeto en un contexto diferente del que se declara (esto también ocurre con los argumentos pasados por referencia).
- No coincidencia de por vida La vida útil de un puntero puede ser diferente de la vida útil del objeto al que apunta, y eso puede conducir a referencias no válidas (SEGFAULTS) o basura.
- Puntero aritmético . Algunos lenguajes de programación permiten la manipulación de punteros como enteros, y eso significa que los punteros pueden apuntar a cualquier parte (incluidos los lugares más inesperados cuando hay un error). Para utilizar la aritmética de puntero correctamente, un programador debe conocer los tamaños de memoria de los objetos señalados, y eso es algo más en lo que pensar.
- Conversiones de tipos La capacidad de lanzar un puntero de un tipo a otro permite sobrescribir la memoria de un objeto diferente del previsto.
Es por eso que un programador debe pensar más a fondo cuando usa punteros (no sé acerca de los dos niveles de abstracción ). Este es un ejemplo de los errores típicos cometidos por un novato:
Pair* make_pair(int a, int b)
{
Pair p;
p.a = a;
p.b = b;
return &p;
}
Tenga en cuenta que un código como el anterior es perfectamente razonable en lenguajes que no tienen un concepto de punteros, sino uno de nombres (referencias), objetos y valores, como los lenguajes de programación funcionales y los lenguajes con recolección de basura (Java, Python). .
La dificultad con las funciones recursivas ocurre cuando las personas sin suficientes conocimientos matemáticos (donde la recursividad es común y se requiere conocimiento) intentan abordarlas pensando que la función se comportará de manera diferente dependiendo de cuántas veces se haya llamado antes . Ese problema se agrava porque las funciones recursivas se pueden crear de una manera en la que hay que pensar de esa manera para comprenderlas.
Piense en funciones recursivas con punteros que se pasan, como en una implementación de procedimiento de un árbol rojo-negro en el que la estructura de datos se modifica en el lugar; Es algo más difícil de pensar que una contraparte funcional .
No se menciona en la pregunta, pero el otro problema importante con el que los principiantes tienen dificultades es la concurrencia .
Como otros han mencionado, hay un problema adicional no conceptual con algunas construcciones de lenguaje de programación: es que incluso si entendemos, los errores simples y honestos con esas construcciones pueden ser extremadamente difíciles de depurar.