Tengo una buena comprensión de la eliminación de referencias operador, la dirección del operador y punteros en general.

Sin embargo me confundo cuando veo cosas como esta:

int* returnA() {
    int *j = &a;
    return j;
}

int* returnB() {
    return &b;
}

int& returnC() {
    return c;
}

int& returnC2() {
    int *d = &c;
    return *d;
}
  1. En returnA() estoy pidiendo a devolver un puntero; solo para aclarar esto funciona porque j es un puntero?
  2. En returnB() estoy pidiendo a devolver un puntero; desde un puntero apunta a una dirección, la razón por la que returnB() funciona es porque me estoy volviendo &b?
  3. En returnC() yo estoy pidiendo una dirección de int a ser devueltos. Cuando regrese c es el & operador automáticamente «anexado» c?
  4. En returnC2() estoy pidiendo de nuevo para una dirección de int a ser devueltos. ¿*d Trabajo porque los punteros apuntan a una dirección?

Suponga que a, b, c se inicializan como enteros como Global.

Alguien puede validar si estoy en lo correcto con todos los cuatro de mis preguntas?

  • Las respuestas a estas preguntas dependen totalmente de las declaraciones de un, b, y c, que parecen haber desaparecido desde el código.
  • Suponga que a, b, c son inicializadas.
  • Las variables son enteros.
InformationsquelleAutor | 2010-05-14

6 Comentarios

  1. 28

    En returnA() estoy pidiendo a devolver un puntero; solo para aclarar esto funciona porque j es un puntero?

    Sí, int *j = &a inicializa j a punto para a. A continuación, devolver el valor de j, que es la dirección de a.

    En returnB() estoy pidiendo a devolver un puntero; desde un puntero apunta a una dirección, la razón por la que returnB() funciona es porque me estoy volviendo &b?

    Sí. Aquí sucede lo mismo que arriba, en un solo paso. &b da la dirección de b.

    En returnC() yo estoy pidiendo una dirección de int para ser devueltos. Cuando yo regrese, c es el & operador automáticamente?

    No, es una referencia a un int, que se devuelve. Una referencia no es una dirección de la misma manera como un puntero es – es sólo un nombre alternativo para una variable. Por lo tanto no es necesario aplicar la & operador para obtener una referencia de una variable.

    En returnC2() yo estoy pidiendo de nuevo para una dirección de int para ser devueltos. No *d trabajo porque los punteros apuntan a una dirección?

    De nuevo, es una referencia a un int, que se devuelve. *d se refiere a la variable original c (cualquiera que sea), señalado por c. Y esto puede implícitamente se convirtió en una referencia, como en returnC.

    Punteros no en general que señale a una dirección (a pesar de que puede – por ejemplo, int** es un puntero a puntero a int). Punteros son una dirección de algo. Al declarar el puntero como something*, que something es la cosa que el puntero apunta. Así que en mi ejemplo anterior, int** declara un puntero a un int*, que pasa a ser un puntero a sí mismo.

    • Puede usted por favor proporcione una respuesta coherente a la tercera edición (la returnC función ())? Aunque c no es una variable de referencia, ¿por qué la función de aceptar c como valor de retorno, incluso a pesar de que las demandas de referencias y una variable de tipo entero se devuelve?
    • Creo que Tyler lo explicó muy bien en su respuesta a continuación, así que me upvote y se adhieren al principio SECO 🙂
    • He leído lo de Tyler escribió cuidadosamente. Él ya no responde a mi pregunta, o tal vez no estoy entendiendo algo. Le pido a usted a leer lo que estoy escribiendo. Usted escribió que No, es una referencia a un int, que se devuelve. Así que cuando me hacen un tipo de función a ser int&, qué dice el programador que una referencia de debe será devuelto o que una referencia de debe ser y será devuelve? Si el anterior caso, es cierto que el código no debe trabajar. Pero porque lo hace, esto último es cierto. Todo lo que estoy pidiendo es la razón por qué? Es esta implícito un proceso de conversión o algo?
    • al declarar el tipo de función int&, usted dice que se devuelve una referencia por ella, y punto. Una referencia es simplemente un alias para una variable, así que no hay necesidad de conversión. Igual, aunque ChosenTorture es más probable que no su nombre real, todavía no tenía necesidad de someterse a ningún tipo de conversión cuando se registra en StackOverflow, ¿no? 😉 La gente de aquí se refieren a usted como ChosenTorture, pero tu mamá probablemente te llama en una totalmente diferente nombre, pero es el mismo todo el tiempo. Del mismo modo, después de la ejecución de int& x = returnC(), x se refieren a la misma variable como c.
  2. 74

    Aunque Pedro respondió a su pregunta, una cosa que es claramente confuso que es el de los símbolos * y &. La parte difícil acerca de conseguir su cabeza alrededor de estos es que ambos tienen dos significados diferentes que tienen que ver con el direccionamiento indirecto (incluso la exclusión de la tercera significados de * para la multiplicación y la & por bit a bit-y).

    • *, cuando se utiliza como parte de un tipo
      indica que el tipo es un puntero:
      int es un tipo, por lo que int* es un
      puntero-a-int tipo, y int** es un
      puntero a puntero-a-int tipo.

    • & cuando se utiliza como parte de un tipo indica que el tipo es una referencia. int es un tipo, por lo que int& es una referencia-a-int (no hay tal cosa como la referencia a de referencia). Las referencias y los punteros se utilizan para cosas similares, pero son bastante diferentes y no son intercambiables. Una referencia es pensado como un alias o nombre alternativo, para una variable existente. Si x es un int, entonces usted puede simplemente asignar int& y = x para crear un nuevo nombre de y para x. Epílogos, x y y puede ser utilizado indistintamente para referirse al mismo entero. Los dos principales implicaciones de esto son que las referencias no puede ser NULO (ya que no debe ser un original de la variable de referencia), y que no es necesario el uso de cualquier operador especial para obtener el valor original (porque es sólo un nombre alternativo, no es un puntero). Las referencias también pueden no ser reasignados.

    • * cuando se utiliza como un operador unario realiza una operación llamada eliminar (que no tiene nada que ver con referencia tipos!). Esta operación sólo es significativa en punteros. Cuando desreferenciar un puntero, de volver a lo que apunta. Por lo tanto, si p es un puntero-a-int, *p es el int señalado.

    • & cuando se utiliza como un operador unario realiza una operación llamada dirección de. Eso es bastante auto-explicativo; si x es una variable, entonces &x es la dirección de x. La dirección de una variable se puede asignar a un puntero al tipo de la variable. Por lo tanto, si x es un int, entonces &x se puede asignar a un puntero de tipo int*, y ese puntero que apunta a una x. E. g. si asigna int* p = &x, entonces *p puede ser utilizado para recuperar el valor de x.

    Así que recuerda, el tipo sufijo & es para referencias, y no tiene nada que ver con la unario consultorio &, que tiene que ver con la obtención de direcciones para su uso con los punteros. Los dos usos son completamente ajenos. Y * como un tipo sufijo declara un puntero, mientras que * como un operador unario realiza una acción en punteros.

    • Gracias por una de las más claras explicaciones que he visto sobre estos operadores.
    • Muy claro muchas gracias!
    • Ver finalmente una solución que me puedan ayudar a envolver mi cabeza alrededor de estas dos cosas
    • Muy bonita respuesta debería haber sido aceptado el uno.
    • Muy bien hecho, señor!
    • Esta es la mejor y más clara explicación de * y & que he leído jamás! Toma mis +50 recompensa por favor 🙂

  3. 5

    Tyler, que fue muy útil la explicación, hice un experimento utilizando el depurador de visual studio para aclarar esta diferencia aún más:-

    int sample = 90;
    int& alias = sample;
    int* pointerToSample  = &sample;
    
    Name                  Address                        Type
    &alias                0x0112fc1c {90}                int *
    &sample               0x0112fc1c {90}                int *
    pointerToSample       0x0112fc1c {90}                int *
    *pointerToSample    90                       int
    alias   90                                       int &
    &pointerToSample      0x0112fc04 {0x0112fc1c {90}}   int * *

    Diseño De Memoria

    PointerToSample       Sample/alias
    _______________......____________________
    0x0112fc1c |          |   90   |
    ___________|___.....__|________|_______...
    
    [0x0112fc04]  ...      [0x0112fc1c
  4. 3

    En returnC() y returnC2() no está pidiendo para devolver la dirección.

    Ambas funciones devuelven referencias a objetos.

    Una referencia no es la dirección de la nada no es un nombre alternativo de algo (esto puede significar que el compilador puede (o no dependiendo de la situación) use una dirección para representar el objeto (como alternativa, también puede saber que para mantenerlo en el registro)).

    Todos sabemos que una los puntos de referencia a un objeto específico.

    Mientras que una referencia a sí mismo no es un objeto sólo un nombre alternativo.

    • Esto es donde yo estaba confundido, pensé que me estaba volviendo direcciones; no de «alias».
  5. 2

    Todos sus ejemplos producir indefinido comportamiento en tiempo de ejecución. Ustedes están regresando a los punteros o referencias a elementos que desaparecen después de la ejecución sale de la función.

    Permítanme aclarar:

    int * returnA()
    {
      static int a;  //The static keyword keeps the variable from disappearing. 
      int * j = 0;   //Declare a pointer to an int and initialize to location 0.
      j = &a;        //j now points to a.
      return j;      //return the location of the static variable (evil).
    }

    En su función, la variable j se asigna a punto para a‘s ubicación temporal. Al salir de la función de la variable a desaparece, pero es antigua ubicación es devuelta a través de j. Desde a ya no existe en la ubicación indicada por j, un comportamiento indefinido que va a suceder con el acceso a *j.

    Variables dentro de las funciones no debe ser modificado a través de la referencia o puntero por otro código. Puede suceder, aunque se produce un comportamiento indefinido.

    Ser pedante, los punteros devuelto debe ser declarado como puntero a constante de datos. Las referencias devuelto debe ser const:

    const char * Hello()
    {
      static const char text[] = "Hello";
      return text;
    }

    La función anterior devuelve un puntero a constante de datos. Otro código de acceso (leer) los datos estáticos, pero no puede ser modificado.

    const unsigned int& Counter()
    {
      static unsigned int value = 0;
      value = value + 1;
      return value;
    }

    En la función anterior, la value se inicializa a cero en la primera entrada. Todos la próxima ejecución de esta función causa value se incrementa en uno. La función devuelve una referencia a un valor constante. Esto significa que otras funciones puede utilizar el valor (de lejos) como si fuera una variable (sin tener que desreferenciar un puntero).

    En mi forma de pensar, un puntero se utiliza para un parámetro opcional o un objeto. Una referencia se pasa cuando el objeto debe existir. Dentro de la función, una referencia a un parámetro significa que el valor existe, sin embargo un puntero debe comprobarse null antes de eliminar la referencia de la misma. También, con una referencia, no hay más garantía que el objeto de destino es válido. Un puntero puede apuntar a una dirección no válida (no nulo) y causar un comportamiento indefinido.

    • Si usted asume a, b, y c son globales, a continuación, el código de ejemplo está bien. Si hubieran sido declarada como la estática dentro de las funciones, también estaría bien. La estática no se moverán dentro y fuera ubicaciones temporales. Sus ubicaciones son estáticos. Siempre se puede devolver un puntero o una referencia a una variable estática. No es siempre una buena idea (re-entrancy y multithreading), pero funciona.
  6. 1

    Semánticamente, referencias actúan como direcciones. Sin embargo, sintácticamente, son el compilador del trabajo, no el tuyo, y usted puede tratar de una referencia como si es la original del objeto que señala, incluyendo la unión de otras referencias y que ellos se refieren al objeto original también. Decir adiós a la aritmética de punteros en este caso.

    La desventaja de esto es que usted no puede modificar lo que se refieren – están obligados a construir el tiempo.

Dejar respuesta

Please enter your comment!
Please enter your name here