Lección 6: Introducción a los punteros
Los punteros son una herramienta de programación muy potente. Ellos pueden hacer algunas cosas mucho más fáciles, ayudar a mejorar la eficiencia de su programa, e incluso le permiten manejar una cantidad ilimitada de datos. Por ejemplo, el uso de punteros, es una manera de tener una función de modificar una variable pasada a la misma. También es posible usar punteros a asignar dinámicamente la memoria, lo que significa que usted puede escribir programas que pueden manejar cantidades casi ilimitadas de datos que en el momento - no es necesario conocer, al escribir el programa, la cantidad de memoria que necesita. Oh, eso es genial. En realidad, es muy fresco, como veremos en algunos de los tutoriales que vienen. Por ahora, vamos a tener una base en la manija de lo que los punteros son y cómo usarlos.
¿Cuáles son los punteros? ¿Por qué importa?
Los punteros, son bien llamado: que "punteros" a las ubicaciones en la memoria. Piense en una fila de cajas de seguridad ,de varios tamaños en un banco local. Cada caja de seguridad tendrá un número asociado a ella para que el cajero rápidamente puede mirar hacia arriba. Estos números, son como las direcciones de memoria de las variables. Un puntero en el mundo de cajas de seguridad sería simplemente cualquier cosa que se almacena el número, de otra caja de seguridad. Tal vez usted tiene un tío rico, que almacena los objetos de valor en su caja de seguridad, pero decidió poner la ubicación real en otro, más pequeño, la caja de seguridad que sólo se almacena en una tarjeta con el número de la caja grande con las joyas reales. La caja de seguridad con la tarjeta, se almacena la ubicación de otro cuadro, sería equivalente a un puntero. En el equipo, los punteros son variables, que se ocupan de almacenar la memorias, por lo general las direcciones de otras variables.
Lo interesante, es que una vez que se puede hablar de la dirección de una variable, a continuación, será capaz de ir a esa dirección y recuperar los datos almacenados en ella. Si le sucede que tiene un pedazo enorme de datos que desea pasar a una función, que es mucho más fácil pasar su ubicación a la función, que copiar todos los elementos de los datos! Por otra parte, si usted necesita más memoria para su programa, usted puede solicitar más memoria del sistema - ¿cómo se consigue "Atrás" que la memoria? El sistema le indica dónde se encuentra en la memoria, es decir, se obtiene una dirección de memoria de nuevo. Y usted necesita punteros para almacenar la dirección de memoria.
Una nota acerca de los términos: el puntero la palabra puede referirse a una dirección de memoria en sí, o una variable que almacena una dirección de memoria. Por lo general, la distinción no es realmente importante: si usted pasa una variable, a un puntero, a una función, que está pasando el valor almacenado en el puntero - la dirección de memoria. Cuando quiero hablar de una dirección de memoria, me referiré a ella como una dirección de memoria, y cuando quiero una variable que almacena una dirección de memoria, voy a llamar a un puntero. Cuando una variable almacena la dirección de otra variable, que voy a decir que es "apuntar a" esa variable.
Puntero Sintaxis
Los Punteros requiere un poco de nueva sintaxis, porque cuando usted tiene un puntero, necesita la capacidad de solicitar tanto la posición de memoria que almacena y el valor almacenado en esa ubicación de memoria. Por otra parte, ya que los punteros son un poco especiales, es necesario indicar al compilador cuando se declara la variable de puntero que la variable es un puntero, y decirle al compilador qué tipo de memoria que apunta.
La declaración de puntero tiene el siguiente aspecto:
<variable_type> * NOMBRE;
Por ejemplo, puede declarar un puntero que almacena la dirección de un entero con la siguiente sintaxis:
int * points_to_integer;
Observe el uso de la *. Esta es la clave para declarar un puntero, y si lo añade directamente al nombre de la variable, se declara la variable a un puntero. Gotcha menor: si se declara varios punteros en la misma línea, debe preceder a cada uno de ellos con un asterisco:
/ / Un puntero, un int int * regulares pointer1, nonpointer1; / / dos punteros int * pointer1, * pointer2;
Como ya he mencionado, hay dos maneras de utilizar el puntero para acceder a la información: es posible tener que dar la dirección real a otra variable. Para ello, basta con utilizar el nombre del puntero sin *. Sin embargo, para acceder a la ubicación real de la memoria, utiliza el *. El nombre técnico para esta hacer esto es eliminar las referencias al puntero, en esencia, que está tomando la referencia a alguna dirección de memoria y después de él, para recuperar el valor real. Puede ser difícil hacer un seguimiento de cuándo se debe agregar el asterisco. Recuerde que el uso natural del puntero es almacenar una dirección de memoria, de modo que cuando se utiliza el puntero:
call_to_function_expecting_memory_address (puntero);
a continuación, se evalúa a la dirección. Usted tiene que agregar algo extra, el asterisco, con el fin de recuperar el valor almacenado en la dirección. Probablemente haré un montón. Sin embargo, el propio puntero se supone que para almacenar una dirección, por lo que cuando se utiliza el puntero al descubierto, se obtiene que la dirección de la espalda.
Apuntando a algo: Recuperación de una dirección
A fin de tener un puntero en realidad apuntan a otra variable que es necesario contar con la dirección de memoria de esa variable también. Para obtener la dirección de memoria de una variable (su ubicación en la memoria), y poner el signo delante del nombre de la variable. Esto hace que dar su dirección. Esto se llama el operador de dirección, porque devuelve la dirección de memoria. Convenientemente, tanto "y" comercial y la dirección de comenzar con una, eso es una manera útil de recordar que se utiliza y para obtener la dirección de una variable.
Por ejemplo:
# Include <iostream> using namespace std; int main () {int x; / / A int normal entero p * / / Un puntero a un entero p = &x; / / Léelo, "asignar la dirección de x p "cin>> x; / / Poner un valor en x, se podría también utilizar * p aquí cin.ignore (); cout <<* p <<" \ n "; / / Tenga en cuenta el uso de la * Para obtener el cin.get valor ();}
El devuelve el valor almacenado en x. ¿Por qué es eso? Bueno, echemos un vistazo al código. El entero se llama x. Un puntero a un entero se define como p. Luego se almacena la ubicación de memoria de x en el puntero mediante el operador de dirección (&) para obtener la dirección de la variable. Uso del signo es un poco como mirar la etiqueta de la caja de seguridad para ver su número en lugar de buscar dentro de la caja, para conseguir lo que almacena. El usuario entonces entra un número que se almacena en la variable x, recuerda, esta es la misma ubicación que es apuntado por p.
La siguiente línea a continuación, pasa p * a la corte. * P realiza la "eliminación de referencias" operación de p, sino que mira a la dirección almacenada en p, y se va a esa dirección y devuelve el valor. Esto es similar a mirar dentro de una caja de seguridad sólo para encontrar el número de (y, presumiblemente, la clave de la) otro cuadro, que se abra.
Tenga en cuenta que en el ejemplo anterior, el puntero se inicializa para que apunte a una dirección de memoria específica antes de su uso. Si este no era el caso, podría estar apuntando a nada. Esto puede llevar a consecuencias muy desagradables para el programa. Por ejemplo, el sistema operativo probablemente le impedirá acceder a la memoria que se conoce su programa, no posee: esto hará que el programa se bloquee. Para evitar chocar su programa, siempre se debe inicializar punteros antes de usarlos.
También es posible inicializar punteros con memoria libre. Esto permite la asignación dinámica de memoria de serie. Es muy útil para la creación de estructuras llamadas listas enlazadas. En este tema difícil es demasiado complejo para este texto. La comprensión de las nuevas palabras clave y borrar, sin embargo, ser tremendamente útil en el futuro.
La nueva palabra clave se utiliza para inicializar punteros con la memoria de la tienda libre (una sección de memoria disponible para todos los programas). La sintaxis es similar al ejemplo:
int * ptr = new int;
Se inicializa ptr para que apunte a una dirección de memoria de int tamaño (porque las variables tienen tamaños diferentes, el número de bytes, esto es necesario). La memoria que se apunta a estar disponible para otros programas. Esto significa que el codificador cuidado debe liberar esta memoria al final de su uso.
El operador delete libera la memoria asignada a través de nuevos. Para ello, la sintaxis es como en el ejemplo.
eliminar ptr;
Después de eliminar un puntero, es una buena idea para restablecer de modo que apunte a 0. Cuando 0 es asignado a un puntero, el puntero se convierte en un puntero nulo, en otras palabras, apunta a nada. De esta manera, cuando haces algo tonto con el puntero (que pasa mucho, incluso con los programadores con experiencia), se encuentra inmediatamente en lugar de más tarde, cuando usted ha hecho un daño considerable.
De hecho, el concepto de puntero nulo se utiliza frecuentemente como una forma de indicar un problema - por ejemplo, algunas de las funciones remanentes de retorno C 0, si bien no puede asignar memoria (en particular, la función malloc ). Usted quiere estar seguro de manejar esto correctamente, si alguna vez otro uso o funciones de C malloc que devuelven un "puntero NULL" en caso de fallo.
En C + +, si una llamada a la nueva falla porque el sistema está fuera de la memoria, entonces será "una excepción". Por el momento, usted no necesita preocuparse demasiado acerca de este caso, pero usted puede leer más acerca de lo que sucede cuando el nuevo no .
Balance de los punteros
Los punteros se puede sentir como un tema muy confuso al principio pero creo que cualquier persona puede llegar a apreciar y entender ellos. Si usted no siente que absorbe todo lo relacionado con ellos, acaba de tomar unas cuantas respiraciones profundas y volver a leer la lección. Usted no debe sentirse como usted ha comprendido plenamente todos los matices de cuándo y por qué es necesario utilizar punteros, aunque podrá tener una idea de algunos de sus usos básicos.