Pregunta

AKA - ¿Qué esta obsesión con los punteros?

Tener sólo usa realmente moderno, lenguajes orientados a objetos como ActionScript, Java y C#, yo no entiendo muy bien la importancia de los punteros y qué hacer con ellos.Lo que me estoy perdiendo aquí?

¿Fue útil?

Solución

Todo es cuestión de direccionamiento indirecto:La capacidad de no lidiar con los datos, pero decir "voy a dirigir a algunos datos, sobre la que hay".Tiene el mismo concepto en Java y C#, pero sólo en formato de referencia.

Las principales diferencias son que las referencias son efectivamente inmutable señales - que siempre apuntan a algo.Esto es útil, y fácil de entender, pero menos flexible que el de C puntero del modelo.C punteros son señales de que puede felizmente a escribir.Usted sabe que la cadena que estamos buscando es el siguiente puerta a la cadena que se apunta a?Bueno, basta con modificar ligeramente la señal.

Esto complementa bien con C "cerca del hueso, el bajo nivel de conocimiento requerido" enfoque.Nosotros saber que un char* foo consiste en un conjunto de caracteres que comienza en la posición indicada por el foo señal.Si también sabemos que la cadena es de al menos 10 caracteres de largo, se puede cambiar la señal a (foo + 5) a punto a la misma cadena, pero el inicio de la mitad de la longitud.

Esta flexibilidad es útil cuando usted sabe lo que está haciendo, y la muerte si no (donde "saber" es más que "conocer el lenguaje", es "conocer el estado exacto del programa").Se equivocan, y su señal se dirige hacia el borde de un acantilado.Las referencias no te dejan tocar el violín, así que es mucho más seguro de que usted puede seguir sin riesgo (especialmente cuando se combina con reglas como "Un objeto de referencia nunca va a desaparecer", como en la mayoría de recolección idiomas).

Otros consejos

Te estás perdiendo de mucho!La comprensión de cómo el equipo funciona en los niveles inferiores es muy útil en varias situaciones.C y ensamblador va a hacer eso para usted.

Básicamente un puntero permite escribir cosas a cualquier punto en la memoria de la computadora.En la más primitiva de hardware/OS o en sistemas integrados, esto realmente podría hacer algo útil.Decir gire el blinkenlichts encendido y apagado de nuevo.

Por supuesto, esto no funciona en los sistemas modernos.El sistema operativo es el Señor y Maestro de la memoria principal.Si intenta tener acceso a una incorrecta ubicación de la memoria, el proceso va a pagar por su arrogancia, con su vida.

En C, los punteros son la manera de pasar las referencias a los datos.Cuando se llama a una función, usted no desea copiar un millón de bits a una pila.En lugar de que usted acaba de decir de donde los datos residen en la memoria principal.En otras palabras, darle un puntero a los datos.

En cierta medida eso es lo que sucede con Java.Pasar las referencias a los objetos, no los objetos en sí.Recuerde que, en última instancia, cada objeto es un conjunto de bits en el equipo principal de la memoria.

Los punteros son para la manipulación directa de los contenidos de la memoria.

Es hasta usted si usted piensa que esto es una buena cosa que hacer, pero es la base de cómo algo que se hace en C o ensamblador.

Los lenguajes de alto nivel ocultar punteros detrás de las escenas:por ejemplo, una referencia en Java se implementa como un puntero en casi cualquier JVM vas a venir a través, que es por qué se llama NullPointerException en lugar de NullReferenceException.Pero no deje que el programador acceder directamente a la dirección de memoria que apunta, y no puede ser modificado para tener un valor distinto de la dirección de un objeto del tipo correcto.Por lo que no ofrecen la misma potencia (y la responsabilidad) de que los punteros en lenguajes de bajo nivel a hacer.

[Editar:esta es una respuesta a la pregunta '¿por qué esta obsesión con los punteros?'.Todos los he comparado es un ensamblador/C estilo de punteros con Java referencias.La pregunta del título ha cambiado desde entonces:había establecido para responder a la nueva pregunta que me podría haber mencionado referencias en otros idiomas que no sean Java]

Esto es como preguntar, "¿qué esta obsesión con las instrucciones de la CPU?¿Se me olvida algo por no rociar x86 MOV instrucciones por todo el lugar?"

Usted acaba de necesidad los punteros cuando la programación a bajo nivel.En la mayoría de los de más alto nivel lenguaje de programación implementaciones, los punteros se utilizan tan ampliamente como en C, pero oculto para el usuario por el compilador.

Así que...No te preocupes.Estás usando punteros ya-y sin los peligros de hacerlo incorrectamente, demasiado.:)

Veo punteros como una transmisión manual de un coche.Si aprendes a conducir con un coche que tiene una transmisión automática, que no hacer un mal conductor.Y todavía se puede hacer casi todo lo que los conductores que han aprendido en un manual de la transmisión puede hacer.Apenas habrá un agujero en el conocimiento de la conducción.Si usted tuvo que conducir un manual que probablemente estaría en problemas.Claro, es fácil entender el concepto básico de la misma, pero una vez que usted tiene que hacer un arranque en pendiente, estás jodido.Pero, todavía hay lugar para las transmisiones manuales.Por ejemplo, los pilotos de autos de carrera deben ser capaces de cambiar para poner el coche a responder de la manera más óptima a las actuales condiciones de competencia.Tener una transmisión manual es muy importante para su éxito.

Esto es muy similar a la programación de la derecha ahora.Hay una necesidad de desarrollo C/C++ en algunos programas de software.Algunos ejemplos son high-end 3D juegos, bajo nivel de software embebido, las cosas en las que la velocidad es una parte crítica del software de propósito, y un menor nivel de lenguaje que permite un acceso más cercano a los datos reales que necesita ser procesada es la clave para que el rendimiento.Sin embargo, para la mayoría de los programadores, este no es el caso y no saber punteros no es paralizante.Sin embargo, yo creo que todo el mundo puede beneficiarse de aprender acerca de C y punteros, y las transmisiones manuales también.

Puesto que usted ha sido programación en lenguajes orientados a objetos, déjame ponerlo de esta manera.

Usted consigue el Objeto a crear una instancia de Objeto B, y se le pasa como parámetro del método al Objeto C.El Objeto C modifica algunos valores en el Objeto B.Cuando vuelva a Objeto de Un código, usted puede ver el cambio de valor en el Objeto B.¿Por qué es esto así?

Porque pasa en un referencia de Objeto de la B a la C del Objeto, no hizo otra copia del Objeto B.De modo que el Objeto a y el Objeto C ambos contienen referencias al mismo Objeto B en la memoria.Los cambios de un lugar y ser visto en otra.Esta es llamada Por Referencia.

Ahora, si el uso de tipos primitivos en su lugar, como int o float, y se pasan como parámetros del método, los cambios en el Objeto C no puede ser visto por Un Objeto, porque el Objeto a simplemente pasar un copia en lugar de una referencia de su propia copia de la variable.Esta es llamada Por Valor.

Probablemente usted ya lo sabía.

Volviendo al lenguaje C, la Función de Una pasa a la Función B de algunas variables.Estos parámetros de la función de forma nativa copias, Por Valor.En orden para la Función B para manipular la copia que pertenecen a Una Función, la Función debe pasar un puntero para la variable, por lo que se convierte en un paso Por Referencia.

"Hey, aquí está la dirección de memoria a mi variable de tipo entero.Poner el nuevo valor en el que la ubicación de la dirección y voy a recoger más tarde."

Nota: el concepto es similar, pero no 100% análogo.Los punteros pueden hacer mucho más de lo que acaba de pasar "por referencia".Los punteros permiten funciones para manipular ubicaciones arbitrarias de memoria para cualquier valor requerido.Los punteros también se utilizan para apuntar a nuevas direcciones de código de ejecución de dinámicamente ejecución arbitraria de la lógica, no solo los datos de las variables.Los punteros pueden apuntar incluso otros consejos (doble puntero).Que es potente pero también muy fácil de introducir difíciles de detectar errores y vulnerabilidades de seguridad.

Si usted no ha visto los punteros antes, seguramente estará perdiendo de esta mini-gema:

void strcpy(char *dest, char *src)
{    
        while(*dest++ = *src++);
}

Históricamente, lo que hizo que la programación fue la constatación de que las ubicaciones de la memoria podía contener instrucciones de computadora, y no sólo de datos.

Punteros surgió de la constatación de que las ubicaciones de la memoria también llevar a cabo la dirección de memoria de otros lugares, lo que nos da el direccionamiento indirecto.Sin punteros (a bajo nivel) la más complicada de las estructuras de datos sería imposible.No vinculado-listas, binarias de los árboles o hash-tablas.No pase por referencia, sólo por el valor.Desde los punteros pueden apuntar al código, sin los cuales nosotros también no tienen funciones virtuales o la función de buscar las tablas.

Puedo usar punteros y referencias pesadamente en mi trabajo del día a día...en código administrado (C#, Java) y no administrado (C++, C).Aprendí acerca de cómo lidiar con los punteros y lo que son por el maestro de sí mismo...[Chupete!!][1] Nada más que decir ;)

La diferencia entre un puntero y de referencia es este.Un puntero es una dirección de un bloque de memoria.Puede ser reescrito o en otras palabras, reasignado a algún otro bloque de memoria.Una referencia es simplemente un cambio de nombre de algún objeto.Sólo se puede asignar una vez!Una vez que se le asigna a un objeto, no puede ser asignado a otro.Una referencia no es una dirección, que es otro nombre para la variable.Echa un vistazo C++ FAQ para más información sobre esto.

Link1

LInk2

Actualmente estoy en la cintura, en el diseño de algunos de alto nivel de software empresarial en la que los fragmentos de datos (almacenados en una base de datos SQL, en este caso) se hace referencia por 1 o más entidades.Si un fragmento de datos permanece cuando no hay más entidades de referencia, estamos perdiendo el almacenamiento.Si los puntos de referencia para los datos que no está presente, ese es un gran problema también.

Hay una fuerte analogía entre nuestros problemas, y los de la gestión de la memoria en un idioma que utiliza punteros.Es tremendamente útil para poder hablar con mis colegas en términos de la analogía.No borrar los datos es una "pérdida de memoria".Una referencia que no va a ninguna parte es un "colgando"puntero.Podemos elegir explícito "libera", o podemos implementar "recolección de basura" usando "el recuento de referencias".

Así que aquí, la comprensión de bajo nivel de la gestión de memoria es ayudar a diseñar aplicaciones de alto nivel.

En Java estás usando punteros todo el tiempo.La mayoría de las variables son punteros a objetos, es por ello que:

StringBuffer x = new StringBuffer("Hello");
StringBuffer y = x;
x.append(" boys");
System.out.println(y);

...imprime "Hola chicos" y no "Hola".

La única diferencia en C es que es común a sumar y restar de los punteros - y si te quedas la lógica equivocada puede acabar arruinando con datos que no debería tocar.

Las cadenas son fundamentales para C (y otros idiomas).Cuando la programación en C, usted debes gestionar tu memoria.No acaba de decir "bueno, voy a necesitar un montón de cadenas";usted necesita pensar acerca de la estructura de datos.¿Cuánta memoria se necesita?Cuando va a asignar?Cuando va a librarse de él?Digamos que usted quiere 10 cadenas, cada uno con no más de 80 caracteres.

Bueno, cada cadena es un array de caracteres (81 caracteres - no se puede olvidar el nulo o usted será lo siento!) y, a continuación, cada cadena es en sí mismo en una matriz.El resultado final será una matriz multidimensional algo como

char dict[10][81];

Nota, por cierto, de que dict no es una "cadena" o una "matriz", o un "char".Es un puntero.Cuando intenta imprimir una de esas cadenas, todo lo que estamos haciendo es pasar la dirección de un solo carácter;C se supone que si sólo se inicia la impresión de los caracteres que con el tiempo llegará a un valor nulo.Y se supone que si están en el inicio de una cadena, y saltar hacia adelante 81 bytes, que estará en el inicio de la siguiente cadena.Y, de hecho, tomando el puntero y la adición de 81 bytes que es el única manera posible para saltar a la siguiente cadena.

Así que, ¿por qué son punteros importante?Porque no se puede hacer nada sin ellos.Ni siquiera se puede hacer algo tan simple como imprimir un montón de cadenas;usted sin duda no se puede hacer nada interesante como implementar las listas enlazadas, o hash, o colas, o los árboles, o un sistema de archivos, o algún código de administración de memoria, o un kernel o lo que sea...Usted NECESITA entender, porque C sólo manos un bloque de memoria y vamos a hacer el resto, y hacer cualquier cosa con un bloque de materias primas de la memoria requiere de punteros.

También muchas personas sugieren que la capacidad para entender los punteros se correlaciona altamente con conocimientos de programación.Joel ha hecho de este argumento, entre otros.Por ejemplo

Ahora, yo admiten libremente que la programación con punteros no es necesario en el 90% del código escrito hoy, y de hecho, es muy peligroso en el código de producción.OK.Que está bien.La programación funcional y simplemente no se utiliza mucho en la práctica.De acuerdo.

Pero aún así es importante para algunos de los más emocionantes de los trabajos de programación.Sin punteros, por ejemplo, nunca sería capaz de trabajar en el kernel de Linux.No se puede entender una línea de código en Linux, o, de hecho, cualquier sistema operativo, sin realmente entender a los punteros.

De aquí.Excelente artículo.

Para ser honesto, la mayoría de experimentados desarrolladores tendrán una risa (esperemos amistoso) si usted no sabe punteros.En mi Trabajo anterior, hemos tenido dos nuevas contrataciones del año pasado (recién graduado) que no sabía acerca de los punteros, y que solo fue el tema de conversación con ellos alrededor de una semana.Nadie podía creer cómo alguien podría graduarse sin saber punteros...

Referencias en C++ son fundamentalmente diferentes de las referencias en Java o .NET languages;.NET languages tiene un tipo especial llamado "byrefs", que actúan de forma muy similar a C++ "referencias".

Una referencia de C++ o .NET byref (voy a utilizar este último término, para distinguirlo de .NET referencias) es un tipo especial que no es una variable, sino que tiene información suficiente para identificar una variable (o algo que puede comportarse como una, como una matriz de la ranura) celebradas en otros lugares.Byrefs por lo general sólo se utiliza como función de los parámetros/argumentos, y están destinados a ser efímero.Código que pases un byref a una función garantiza que la variable que se identifica con lo que existirá, al menos, hasta que el retorno de la función, y las funciones generalmente garantía de no mantener ninguna copia de un byref después de su retorno (tenga en cuenta que en C++ la última restricción no se aplica).Por lo tanto, byrefs no puede sobrevivir a las variables identificadas por ello.

En Java y .NET languages, una referencia es un tipo que identifica a un montón de objetos;cada montón de objetos tiene asociada una clase, y el código en el montón de objetos de la clase puede acceder a los datos almacenados en el objeto.El montón de objetos puede conceder fuera de código completa o limitada de acceso a los datos almacenados en el mismo, y/o permitir que fuera de código para llamar a ciertos métodos dentro de su clase.El uso de una referencia a llamar a un método de la clase hará que la referencia a estar disponible para que el método que se pueden utilizar para acceder a los datos (incluso datos privados) dentro de la pila de objetos.

Lo que hace referencias especiales en Java y .NET languages es que mantienen, como un absoluto, invariable, que todos no nulos, se hará referencia a seguir para identificar el mismo montón de objetos, mientras que el de referencia existe.Una vez que no hay referencia a un montón de objeto existe en cualquier lugar del universo, el montón de objetos simplemente dejan de existir, pero no hay forma que un montón de objetos puede dejar de existir, mientras que cualquier referencia a ella existe, ni hay ninguna manera de que un "normal" de referencia a un montón de objetos de forma espontánea convertido en algo más que una referencia a ese objeto.Tanto en Java y .NET tiene especial "débil" referencia de tipos, pero incluso ellos mantener el invariante.Si no débil que las referencias a un objeto existe en ninguna parte del universo, entonces cualquier existentes referencias débiles serán invalidadas;una vez que esto ocurre, ya no hay referencias al objeto y por lo tanto, puede ser invalidado.

Punteros, como C++ referencias y Java/.RED de referencias, identificar objetos, pero a diferencia de los mencionados tipos de referencias que pueden sobrevivir a los objetos que identifican.Si el objeto identificado por un puntero deja de existir, pero el puntero no se, cualquier intento de utilizar el puntero va a resultar en un Comportamiento Indefinido.Si el puntero no se sabe null o para identificar a un objeto que existe en la actualidad, no hay ningún estándar definido manera de hacer nada con ese puntero otros de sobrescribir con algo más.Es perfectamente legítimo que un puntero a seguir existiendo después de que el objeto identificado con lo que ha dejado de hacerlo, a condición de que nunca nada que utiliza el puntero, pero es necesario que algo fuera de el puntero indique si es o no es seguro de usar, ya que no hay forma de pedir el puntero en sí.

La diferencia clave entre los punteros y referencias (de cualquier tipo) es que las referencias siempre pueden ser preguntado si son válidos (que va a ser válida o identificable como nulo), y si se observa a ser válido que lo seguirá siendo mientras existan.Los punteros no se le puede pedir si son válidos, y el sistema no hará nada para asegurarse de que los punteros no ser válida, ni permitir que los punteros que ser válida para ser reconocido como tal.

Durante mucho tiempo yo no entendía punteros, pero entendí matriz de direccionamiento.Por lo que me suele poner juntos algunos de área de almacenamiento para los objetos en una matriz y, a continuación, utilizar un índice para que la matriz como el 'puntero' concepto.

SomeObject store[100];
int a_ptr = 20;
SomeObject A = store[a_ptr];

Un problema con este enfoque es que después he modificado 'A', tendría que volver a aplicarlo a la 'store' de la matriz en orden para que los cambios sean permanentes:

store[a_ptr] = A;

Detrás de las escenas, el lenguaje de programación estaba haciendo varios copia de las operaciones.La mayoría de las veces esto no afecta el rendimiento.Principalmente, el código de error y propensas a errores repetitivos.

Después aprendí a entender punteros, me alejé de la aplicación de la matriz de direccionamiento de enfoque.La analogía es aún bastante válida.Sólo ten en cuenta que el 'almacén' de la matriz es administrada por el lenguaje de programación del tiempo de ejecución.

SomeObject A;
SomeObject* a_ptr = &A;
// Any changes to a_ptr's contents hereafter will affect
// the one-true-object that it addresses. No need to reassign.

Hoy en día, yo sólo uso de punteros cuando no puedo legítimamente copia de un objeto.Hay un montón de razones por las que esto podría ser el caso de:

  1. Para evitar un costoso objeto de copia operación para el bien de rendimiento.
  2. Algún otro factor que no permite una objeto de una operación de copia.
  3. Quieres una llamada a una función que tiene efectos secundarios sobre un objeto (no pasar el objeto, pase el puntero al mismo).
  4. En algunos idiomas - si usted desea devolver más de un valor de un función (aunque por lo general evitarse).

Los punteros son la forma más pragmática de la representación de direccionamiento indirecto en el bajo nivel de los lenguajes de programación.

Los punteros son importantes!Que "apuntar" a una dirección de memoria, y muchas de las estructuras internas son representados como punteros, es decir, Una matriz de cadenas es en realidad una lista de punteros a punteros!Los punteros también puede ser utilizado para la actualización de las variables que se pasan a funciones.

Usted necesita si quiere generar "objetos" en tiempo de ejecución sin pre asignar memoria en la pila

Parámetro de eficiencia - pasando un puntero (Int - 4 bytes) en vez de la copia de un todo (arbitarily grande) objeto.

Las clases de Java se transmiten a través de la referencia (básicamente un puntero), también es cierto, es sólo que en java que oculta al programador.

Programación en lenguajes como C y C++ es mucho más cerca de "metal".Los punteros de mantener una posición de la memoria donde sus variables, datos, funciones, etc.vivir.Usted puede pasar un puntero en lugar de pasar por valor (la copia de los datos y variables).

Hay dos cosas que son difíciles con punteros:

  1. Punteros a punteros, direcciones, etc.puede ser muy críptico.Esto conduce a errores, y es difícil de leer.
  2. La memoria que los punteros punto a menudo se asignan a partir del montón, lo que significa que usted es responsable de liberar la memoria.Más grande que su solicitud sea, más difícil es seguir con este requisito, y se termina con pérdidas de memoria que son difíciles de localizar.

Se podría comparar el comportamiento del puntero a cómo Java objetos pasan a su alrededor, con la excepción de que en Java no tiene que preocuparse de liberar la memoria como esto es manejado por la recolección de basura.De esta manera se consigue las cosas buenas acerca de los punteros, pero no tienen que lidiar con los negativos.Usted todavía puede obtener las pérdidas de memoria en Java, por supuesto, si no de hacer referencia a sus objetos, sino que es un asunto diferente.

También acaba de algo que tenga en cuenta, usted puede usar los punteros en C# (en oposición a la normalidad referencias) mediante el marcado de un bloque de código inseguro.A continuación, puede ejecutar alrededor de cambiar directamente las direcciones de memoria y hacer aritmética de punteros y todos los que la materia de la diversión.Es ideal para muy rápida manipulación de la imagen (el único lugar en el que yo personalmente he utilizado).

Que yo sepa Java y el código de ActionScript no admiten código inseguro y punteros.

Siempre estoy angustiado por el foco en cosas tales como punteros o referencias en los lenguajes de alto nivel.Es muy útil para pensar en un nivel de abstracción más alto en términos del comportamiento de los objetos (o funciones), en contraposición a pensar en términos de "vamos a ver, si me envía la dirección de esta cosa a la que no, luego que lo va a volver a mí a un puntero a otra cosa"

Considerar incluso una simple función de intercambio.Si usted tiene

void swap(int & a, int & b)

o

procedimiento de Intercambio(var a, b :entero)

luego de interpretar estos significa que los valores se pueden cambiar.El hecho de que este está siendo implementado por el paso de las direcciones de las variables es sólo una distracción para el propósito.

Mismo con los objetos --- no creo que de identificadores de objeto como punteros o referencias a "cosas".En su lugar, basta con pensar en ellos como, también, los OBJETOS, a la que puedes enviar mensajes.Incluso en los primitivos lenguajes como C++, puede ir mucho más lejos, mucho más rápido por el pensamiento (y la escritura) en un nivel tan alto como sea posible.

Escribir más de 2 líneas de c o c++ y te voy a encontrar.

Ellos son "punteros" a la ubicación de memoria de una variable.Es como pasar una variable por referencia un poco.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top