¿Cuáles son los casos de uso y las ventajas de los punteros? [cerrado]

10

A menudo me cuesta ver las ventajas de los punteros (a excepción de la programación de bajo nivel).

¿Por qué usar char * en lugar de String o char [] o qué ventajas aporta la aritmética de puntero?

Entonces, ¿cuáles son los pros y los casos de uso de punteros?

OliverS
fuente
66
Esto va a parecer un poco elitista, pero en mi humilde opinión, si tiene que preguntar sobre los pros y los contras de los punteros, lo más probable es que no los necesite.
Jas
3
¡Probablemente! ¡Pero la pregunta sigue siendo válida!
Zolomon
1
Esto tampoco es realmente independiente del lenguaje, ya que no todos los lenguajes de programación tienen punteros reales en el sentido C.
David Thornley

Respuestas:

6

Los punteros son necesarios para la ubicación dinámica de la memoria, muchas estructuras de datos y el manejo eficiente de grandes cantidades de datos. Sin punteros, tendría que asignar todos los datos del programa globalmente o en funciones o su equivalente, y no tendría ningún recurso si la cantidad de datos creciera más de lo que originalmente había permitido. Dudo en usar absolutos aquí, pero que yo sepa, todos los lenguajes de computadora modernos tienen punteros de una forma u otra.

En la mayoría de los lenguajes que usan punteros, hay ciertos tipos de referencias que son punteros, y tal vez ciertos tipos de referencias que no lo son, y no hay más diferencia de notación. Una conscelda Lisp es un par de punteros, aunque a fixnumno es un puntero. En Java, la variable utilizada para la instancia de una clase es un puntero, pero intno lo es. La sintaxis del lenguaje no refleja eso.

C es inusual porque los punteros son opcionales, explícitos y permiten la aritmética explícita de punteros. Es perfectamente posible escribir struct foo bar; struct foo * baz;, y una vez que haya asignado memoria baz, puede usar ambos bary bazrepresentar struct foos. Como los punteros son opcionales, es útil tener diferencias notacionales. (Es esencial en C ++ para los punteros inteligentes, tal como se indica boost::shared_ptr<foo> bar;, bar.reset()tiene un significado y bar->reset()es probable que tenga un gran uno diferente).

(En realidad, los punteros explícitos a menudo se usaban en otros lenguajes cuando C se estaba desarrollando originalmente, como ^en Pascal. C es un lenguaje más antiguo que la mayoría de uso común en la actualidad, y se nota).

Uno de los objetivos de diseño de C era escribir Unix y, por lo tanto, necesitaba manejar ubicaciones de memoria de manera detallada. (C es en realidad uno de una familia de lenguajes de implementación de sistemas comunes cuando se diseñó, otro ejemplo es Cybol para computadoras Control Data. C es el que se convirtió en un gran éxito). Por lo tanto, es posible manipular los punteros C directamente, asignando direcciones de memoria y calculando nuevas. Esto también condujo a algunas decisiones de diseño en C. Las matrices C se basan en gran medida en la aritmética del puntero, y de hecho una matriz se desintegra en un puntero en muchas situaciones. El paso de variables a funciones C por referencia se realiza mediante puntero. No había una gran necesidad de matrices y variables de paso por referencia en la forma que tenían otros lenguajes contemporáneos, por lo que C no los obtuvo.

Entonces, la respuesta es que, en la mayoría de los idiomas hoy en día, usas punteros constantemente sin que se te recuerde el hecho. En C, y en menor medida en C ++, utiliza punteros para hacer cosas de bajo nivel o para lograr cosas de alto nivel para las que no hay una notación especial.

David Thornley
fuente
muy buena respuesta
Kate Gregory
1
Acepto esta respuesta porque describe mejor la diferencia que no pude comprender entre punteros en C / C ++ y Referencia en Java.
OliverS
Sería bueno agregar una breve explicación de por qué Java no utiliza punteros para aclarar mejor la "estafa" percibida por Gosling (el creador principal de Java).
Guido Anselmi
10

Estructuras de datos complejas. No puede construir algo como una lista vinculada o un árbol binario sin punteros.

No hay "pros" y "contras" de punteros. Son solo una herramienta, como un martillo.

zvrba
fuente
55
En Java, no hay punteros. Sin embargo, es posible construir una lista vinculada y un árbol binario. Hay una diferencia entre referencias (como en Java) y punteros (como en C).
StartClass0830
77
No hay diferencia entre referencias y punteros. La aritmética del puntero es específica de C; Hay otros idiomas que tienen punteros, pero no tienen aritmética de punteros (por ejemplo, Pascal).
zvrba
1
Punteros y referencias no son sinónimos como piensas. Lea esto para ver las diferencias. stackoverflow.com/questions/57483/…
StartClass0830
44
Para abordar los dos primeros elementos de esa lista: las referencias de Java PUEDEN reasignarse y PUEDEN apuntar a nulo. La característica distintiva de un puntero es que le permite hacer referencia indirecta a otro objeto. Mi prueba de fuego es: si puede construir una estructura de datos circular (que puede hacerlo con referencias de Java), es un puntero. (Tenga en cuenta que no puede construir una estructura de datos circular con referencias de C ++.)
zvrba
1
Hay una diferencia entre punteros y referencias. C #, por ejemplo, tiene ambos . ( blogs.msdn.com/b/ericlippert/archive/2009/02/17/… )
Steven Evers
2
  • Con punteros puede asignar y desasignar memoria en tiempo de ejecución.
  • Y puede usar grandes estructuras de datos fuera de su alcance permitido sin ser copiado.

Las referencias en C ++, Java y otros tipos de lenguajes son solo 'punteros seguros'. Y estas referencias se usan mucho en Java.

Gulshan
fuente
1
Las referencias en C ++ NO son punteros seguros. Las referencias en C ++ no tienen nada que ver con los punteros. Las referencias en C ++ son alias . No se les puede asignar NULLy no se pueden modificar después de crearlos.
Billy ONeal
@Billy: las referencias de C ++ generalmente se implementan mediante punteros y funcionan de manera similar en algunas cosas, por lo que la gente sigue pensando en ellas como una especie de puntero restringido.
David Thornley
2

Casi cualquier programa de computadora necesita inspeccionar y cambiar los valores en la memoria (conocidos como espiar y meter, para aquellos de nosotros que tenemos la edad suficiente). Debe controlar dónde están esos valores en la memoria, de modo que el resultado sea predecible (y en ciertos casos, el orden es importante: cargar un código ejecutable es un ejemplo). Por lo tanto, debe tener un tipo de datos que represente una ubicación en la memoria. Incluso si su entorno de programación lo oculta bajo una abstracción, todavía está allí.


fuente
2

char*es un mal ejemplo de punteros. Probablemente sea mejor usar std::string(o algún tipo mejor que maneje su especialidad unicode / ansi / multibyte) que char*. Para casi cualquier otro ejemplo de punteros ( Employee*, PurchaseOrder*, ...), sin embargo, hay muchas ventajas:

  • alcance mayor que una sola función: asigne el objeto en el montón y pase el puntero durante mucho tiempo
  • la función más rápida requiere objetos grandes, ya que no tiene el costo de copia del valor de paso
  • Una forma de habilitar una función para cambiar los parámetros que se le pasan
  • Ahorre espacio y tiempo en colecciones copiando solo una dirección en lugar de un objeto completo

De hecho, los punteros son tan importantes que la mayoría de los idiomas que parecen no tenerlos en realidad solo los tienen. Los tipos de referencia en C # y Java son esencialmente punteros disfrazados de objetos sólidos.

Ahora, la manipulación del puntero ( p++en un puntero, o p += delta) es una historia completamente diferente. Algunas personas piensan que es peligroso, algunas personas piensan que es genial. Pero eso está aún más lejos de tu pregunta.

Kate Gregory
fuente
1

Los punteros pueden ser más rápidos y pueden generar menos gastos generales, tanto en estructuras de datos como en mantener baja la huella de ejecución del programa. (Tenga en cuenta la palabra 'puede').

En general, la regla es que si asignó un recurso, ya sea realizando su propia asignación o haciendo que algo lo haga en su nombre, entonces es su trabajo liberarlo cuando haya terminado.

La carga de hacer lo anterior es volver a colocar la responsabilidad en el desarrollador, en lugar de que el tiempo de ejecución lo haga. Esto tiene algunas ventajas más, ya que las cosas pueden durar más tiempo, cruzar fronteras o eliminarse en momentos más oportunos o no tener que cargar con el peso de un recolector de basura.

En casos exóticos, que generalmente incluyen excepciones y alcance, hay algunos casos extremos que requieren que uno sea un poco más cuidadoso si se evita el código que hace la limpieza. Siendo realistas, estos casos se pueden diseñar alrededor. Vivimos sin código administrado durante muchas décadas.

A menudo, lo que hace que los punteros sean "difíciles" es simplemente no entender lo que está sucediendo a nivel de hardware. No es más que indirección.

Los punteros le brindan mucho más acceso sin procesar, y esto puede ser muy útil, inteligente o necesario. Puede apuntar a cualquier lugar y tratarlo casi como cualquier cosa. Si usas tus poderes divinos para bien, es muy, muy bueno.

La desventaja generalmente es un desperdicio al olvidarse de liberar algo, o al liberarlo más de una vez, o al hacer referencia a algo después de su lanzamiento, o al volver a hacer referencia a algo cuando no está apuntando a ninguna parte. Estas cosas a menudo resultan en choques espectaculares, y para ser honesto, generalmente son indicativos de que tienes un problema lógico, en lugar de que los indicadores sean frágiles.

Si es un desarrollador sólido, el uso de punteros no debería ser más problemático que cualquier otra estructura de datos. Nuevamente, no es ciencia espacial, y la gente lo hizo durante décadas sin siquiera pestañear. Simplemente se enseña menos a fondo en estos días.

Dicho todo esto, a menos que necesite punteros, la conveniencia y los casos exóticos que proporciona una buena recolección de basura hace que trabajar en un entorno administrado sea mucho más agradable. Es genial poder tomar algo de memoria, usarlo y abandonarlo, sabiendo que en algún momento posterior, podría descartarse, si tiene sentido hacerlo. Eso es un poco menos de código por parte del codificador, a cambio de un tiempo de ejecución que levanta un poco más.

Walt Stoneburner
fuente
0

La mejor respuesta está incluida en la pregunta: los punteros son para programación de bajo nivel. De acuerdo, si estás usando C, no usar punteros es como programar con una mano atada a la espalda, pero la respuesta es usar un lenguaje de nivel superior.

Larry Coleman
fuente
-1

Los punteros proporcionan una visibilidad en la máquina que se requiere para la programación más interesante. La mayoría de los idiomas modernos simplemente te ocultan los fragmentos arenosos.

Paul Nathan
fuente