Bueno, básicamente entiendo cómo usar punteros, pero no la mejor manera de usarlos para hacer una mejor programación.
¿Cuáles son los buenos proyectos o problemas para resolver que involucran el uso de punteros para poder entenderlos mejor?
learning
c++
personal-projects
pointers
dysoco
fuente
fuente
Respuestas:
La manipulación de grandes cantidades de datos en la memoria es donde realmente brillan los punteros.
Pasar un objeto grande por referencia es equivalente a pasar un número antiguo simple. Puede manipular las partes necesarias directamente en lugar de copiar un objeto, alterarlo y luego devolver la copia para colocarla en lugar del original.
fuente
El concepto de puntero le permite referirse a los datos por dirección sin duplicar el almacenamiento de datos. Este enfoque permite escribir algoritmos eficientes como:
Clasificación
Al mover datos en un algoritmo de clasificación, puede mover el puntero en lugar de los datos en sí mismos; piense en ordenar millones de filas en una cadena de 100 caracteres; ahorras muchos movimientos de datos innecesarios.
Listas vinculadas
Puede almacenar la ubicación del elemento siguiente y / o anterior y no todos los datos asociados con el registro.
Paso de parámetros
En este caso, pasa la dirección de los datos en lugar de los datos en sí. Nuevamente, piense en un algoritmo de compresión de nombres que se ejecute en millones de filas.
El concepto puede extenderse a estructuras de datos como bases de datos relacionales donde un puntero es similar a una clave foránea . Algunos lenguajes no fomentan el uso de punteros como C # y COBOL.
Se pueden encontrar ejemplos en muchos lugares como:
La siguiente publicación puede ser relevante de alguna manera:
fuente
Me sorprende que ninguna otra respuesta haya mencionado esto: los punteros le permiten crear estructuras de datos no contiguas y no lineales, en las que un elemento puede estar relacionado con muchos otros de formas complejas.
Las listas vinculadas (individual, doble y circularmente vinculadas), árboles (rojo-negro, AVL, trie, binario, partición espacial ...) y gráficos son ejemplos de estructuras que se pueden construir de forma más natural en términos de referencias en lugar de solo valores .
fuente
Una forma simple es en el polimorfismo. El polimorfismo solo funciona con punteros.
Además, utiliza punteros cada vez que necesita una asignación de memoria dinámica. En C, esto generalmente sucede cuando necesita almacenar datos en una matriz, pero no conoce el tamaño en el momento de la compilación. Luego llamaría a malloc para asignar la memoria y un puntero para acceder a ella. Además, lo sepa o no, cuando usa una matriz, usa punteros.
es el equivalente de
Este conocimiento le permite hacer cosas realmente geniales como copiar una matriz completa en una línea:
En c ++, usa new para asignar memoria para un objeto y almacenarlo en un puntero. Hace esto cada vez que necesita crear un objeto durante el tiempo de ejecución en lugar de durante el tiempo de compilación (es decir, un método crea un nuevo objeto y lo almacena en una lista).
Para entender mejor los punteros:
Encuentra algunos proyectos que usan herencia.
Aquí está el proyecto en el que me corté los dientes:
Lea en dos matrices nxn de un archivo y realice las operaciones básicas de espacio vectorial en ellas e imprima su resultado en la pantalla.
Para hacer esto, debe usar matrices dinámicas y consultar sus matrices por punteros, ya que tendrá dos matrices de matrices (matrices dinámicas multidimensionales). Después de terminar ese proyecto, tendrá una muy buena idea de cómo usar punteros.
fuente
Para comprender realmente por qué los punteros son importantes, debe comprender la diferencia entre la asignación de montón y la asignación de pila.
El siguiente es un ejemplo de una asignación de pila:
Los objetos asignados en la pila solo existen durante la ejecución de la función actual. Cuando la llamada a
foo
fuera de alcance también lo hace la variablef
.Un caso en el que esto se convierte en un problema es cuando necesita devolver algo distinto de un tipo integral de una función (por ejemplo, la estructura Foo del ejemplo anterior).
Por ejemplo, la siguiente función daría como resultado el llamado "comportamiento indefinido".
Si desea devolver algo como
struct Foo *
de una función, lo que realmente necesita es una asignación de montón:La función
malloc
asigna un objeto en el montón y devuelve un puntero a ese objeto. Tenga en cuenta que el término "objeto" se usa libremente aquí, que significa "algo" en lugar de objeto en el sentido de la programación orientada a objetos.El programador controla la vida útil de los objetos asignados en el montón. La memoria para este objeto estará reservada hasta que el programador la libere, es decir, llamando
free()
o hasta que el programa salga.Editar : no noté que esta pregunta está etiquetada como una pregunta de C ++. Los operadores de C ++
new
ynew[]
realizan la misma función quemalloc
. Los operadoresdelete
ydelete[]
son análogos afree
. Si biennew
ydelete
debe usarse exclusivamente para asignar y liberar objetos C ++, el uso demalloc
yfree
es perfectamente legal en el código C ++.fuente
Escriba cualquier proyecto no trivial en C y tendrá que averiguar cómo / cuándo usar punteros. En C ++, utilizará principalmente objetos habilitados para RAII que administran punteros internamente, pero en C los punteros sin formato tienen un papel mucho más frecuente. En cuanto a qué tipo de proyecto debe hacer, puede ser algo no trivial:
Recomiendo el último
fuente
Casi todos los problemas de programación que se pueden resolver con punteros se pueden resolver con otros tipos de referencias más seguros (no se refieren a referencias de C ++ , pero el concepto general de CS de tener una variable se refiere al valor de los datos almacenados en otro lugar).
Los punteros al ser una implementación específica de bajo nivel de referencias, donde puede manipular directamente las direcciones de memoria son muy potentes, pero pueden ser un poco peligrosos de usar (por ejemplo, señalar ubicaciones de memoria fuera del programa).
El beneficio de usar los punteros directamente es que serán un poco más rápidos al no tener que hacer ningún control de seguridad. Los lenguajes como Java que no implementan directamente punteros de estilo C sufrirán un ligero impacto en el rendimiento, pero reducirán muchos tipos de situaciones difíciles de depurar.
En cuanto a por qué necesita indirección, la lista es bastante larga, pero esencialmente las dos ideas clave son:
selected_object
que sea una referencia a uno de los objetos es mucho más eficiente que copiar el valor del objeto actual en una nueva variable.fuente
La manipulación de imágenes a nivel de píxel es casi siempre más fácil y rápida con punteros. A veces solo es posible utilizando punteros.
fuente
Los punteros se utilizan en muchos lenguajes de programación debajo de la superficie sin molestar al usuario al respecto. C / C ++ solo te da acceso a ellos.
Cuándo usarlos: tan a menudo como sea posible, porque copiar datos es ineficiente. Cuándo no usarlos: cuando desee dos copias que se puedan cambiar individualmente. (Lo que básicamente terminará copiando el contenido del objeto_1 en otro lugar en la memoria y devolviendo un puntero, esta vez apuntando al objeto_2)
fuente
Los punteros son una parte esencial para la implementación de cualquier estructura de datos en C y las estructuras de datos son una parte esencial de cualquier programa no trivial.
Si desea saber por qué los punteros son tan vitales, le sugiero que aprenda qué es una lista vinculada e intente escribir una sin usar punteros. No le he planteado un desafío imposible (SUGERENCIA: los punteros se utilizan para hacer referencia a ubicaciones en la memoria, ¿cómo hace referencia a las cosas en las matrices?).
fuente
Como un ejemplo de la vida real, construir un libro de órdenes de límite.
El feed ITCH 4.1, por ejemplo, tiene un concepto de órdenes de "reemplazo", donde los precios (y por lo tanto, la prioridad) pueden cambiar. Desea poder tomar órdenes y moverlas a otro lugar. La implementación de una cola de doble extremo con punteros hace que la operación sea muy fácil.
fuente
Al leer los diversos sitios de StackExchange, me doy cuenta de que está de moda hacer una pregunta como esta. A riesgo de críticas y votos negativos, seré honesto. Esto no está destinado a troll o flamear, solo quiero ayudar, al dar una evaluación honesta de la pregunta.
Y esa evaluación es la siguiente: esta es una pregunta muy extraña para hacerle a un programador en C. Casi todo lo que dice es "No sé C." Si analizo un poco más y más cínicamente, hay un trasfondo de seguimiento a esta "pregunta": "¿Hay algún atajo que pueda tomar para adquirir de forma rápida y repentina el conocimiento de un programador de C experimentado, sin dedicar tiempo? para estudio independiente? Cualquier "respuesta" que alguien pueda dar no es un sustituto para ir y hacer el trabajo preliminar de comprender el concepto subyacente y su uso.
Siento que es más constructivo ir a aprender C bien, de primera mano, que ir a la web y preguntarle a la gente esto. Cuando conozca bien C, no se molestará en hacer preguntas como esta, será como preguntar "¿qué problemas se resuelven mejor con un cepillo de dientes?"
fuente
Aunque los punteros realmente brillan mientras se trabaja con objetos de memoria grandes, todavía hay una manera de hacer lo mismo sin ellos.
El puntero es absolutamente esencial para la llamada programación dinámica , es cuando no sabes cuánta memoria necesitarás antes de que se ejecute tu programa. En la programación dinámica, puede solicitar fragmentos de memoria durante el tiempo de ejecución y colocar sus propios datos en ellos, por lo que necesita puntero o referencias (la diferencia no es importante aquí) para poder trabajar con esos fragmentos de datos.
Siempre que pueda reclamar cierta memoria durante el tiempo de ejecución y colocar sus datos en la memoria recién adquirida, puede hacer lo siguiente:
Puede tener estructuras de datos autoextendibles. Esas son estructuras que pueden extenderse reclamando memoria adicional siempre que su capacidad se agote. La propiedad clave de cada estructura autoextensible es que consiste en pequeños bloques de memoria (denominados nodos, elementos de lista, etc., dependiendo de la estructura) y cada bloque contiene referencias a otros bloques. Estas estructuras "vinculadas" crean la mayoría de los tipos de datos modernos: gráficos, árboles, listas, etc.
Puede programar usando el paradigma OOP (Programación Orientada a Objetos). Todo el OOP se basa en el uso de variables no directas, sino de referencias a instancias de clase (denominadas objetos) y su manipulación. No puede existir una instancia única sin punteros (aunque es posible usar clases solo estáticas incluso sin punteros, eso es más bien una excepción).
fuente
Es curioso, acabo de responder una pregunta sobre C ++ y hablé sobre punteros.
La versión corta es que NUNCA necesitas punteros a menos que 1) la biblioteca que estás usando te fuerce 2) Necesitas una referencia anulable.
Si necesita una matriz, una lista, una cadena, etc., simplemente téngala en la pila y use un objeto stl. Los objetos stl que regresan o pasan son rápidos (hecho no verificado) porque tienen un código interno que copia un puntero en lugar de un objeto y solo copiará los datos si le escribe. Este es C ++ normal, ni siquiera el nuevo C ++ 11 que lo hará más fácil para los escritores de bibliotecas.
Su pregunta puede ser respondida en esta parte
Si utiliza un puntero, asegúrese de que esté en una de estas dos condiciones. 1) Está pasando una entrada que puede ser anulable. Un ejemplo es un nombre de archivo opcional. 2) Si quieres regalar la propiedad. Como si pasa o devuelve el puntero, no le quedan NINGUNAS copias ni utiliza el puntero que regala.
Pero no he usado punteros o punteros inteligentes durante mucho tiempo y he perfilado mi aplicación. Corre muy rápido.
NOTA ADICIONAL: Noto que escribo mis propias estructuras y las paso. Entonces, ¿cómo hago esto sin usar punteros? No es un contenedor STL, por lo que pasar por ref es lento. Siempre cargo mi lista de datos / deques / mapas y demás. No recuerdo haber devuelto ningún objeto a menos que fuera algún tipo de lista / mapa. Ni siquiera una cuerda. Miré el código para objetos individuales y noté que hago algo como esto,
{ MyStruct v; func(v, someinput); ... } void func(MyStruct&v, const D&someinput) { fillV; }
así que devuelvo objetos (múltiples) o preasignar / pasar una referencia para llenar (solo).Ahora, si estaba escribiendo su propio deque, mapa, etc., deberá usar punteros. Pero no necesitas hacerlo. Deje que STL y posiblemente aumente la preocupación por eso. Solo necesita escribir datos y las soluciones. No contenedores para contenerlos;)
Espero que ahora nunca uses punteros: D. Buena suerte con libs que te obligan a
fuente
Los punteros son muy útiles para trabajar con dispositivos mapeados en memoria. Puede definir una estructura que refleje (digamos) un registro de control, luego asignarlo a la dirección del registro de control real en la memoria y manipularlo directamente. También puede apuntar directamente a un búfer de transferencia en una tarjeta o chip si la MMU lo ha asignado al espacio de memoria del sistema.
fuente
Veo punteros como mi dedo índice, solemos hacer un par de cosas:
por favor perdona esta pobre respuesta
fuente
Como su pregunta está etiquetada como C ++, responderé su pregunta para ese lenguaje.
En C ++ hay una distinción entre punteros y referencias, por lo tanto, hay dos escenarios en los que los punteros (o punteros inteligentes) son necesarios para facilitar ciertos comportamientos. Se pueden usar en otras circunstancias, sin embargo, se pregunta cómo "es mejor usarlos", y en todas las demás circunstancias hay mejores alternativas.
1. Polimorfismo
Un puntero de clase base le permite llamar a un método virtual que depende del tipo de objeto al que apunta el puntero.
2. Crear objetos persistentes
Los punteros son necesarios al crear un objeto dinámicamente (en el montón en lugar de la pila). Esto es necesario cuando desea que la vida útil de los objetos sea más larga que el alcance en el que se creó.
En términos de "buenos proyectos o problemas para resolver", como ya han dicho otros aquí, cualquier proyecto no trivial utilizará punteros.
fuente