2009-09-15 20 views
20

escribí una función a lo largo de las líneas de esto:¿Qué significa `* &` en una declaración de función?

void myFunc(myStruct *&out) { 
    out = new myStruct; 
    out->field1 = 1; 
    out->field2 = 2; 
} 

Ahora, en una función que llama, podría escribir algo como esto:

myStruct *data; 
myFunc(data); 

que llenará todos los ámbitos en los data. Si omito el '&' en la declaración, esto no funcionará. (O más bien, funcionará solo localmente en la función, pero no cambiará nada en la persona que llama)

¿Podría alguien explicarme qué hace realmente este '*&'? Se ve raro y no puedo darle mucho sentido.

+5

Es sintaxis C++, no C – qrdl

Respuesta

34

El símbolo & en una declaración de variables C++ significa que es reference.

Pasa a ser una referencia a un puntero, lo que explica la semántica que está viendo; la función llamada puede cambiar el puntero en el contexto de llamada, ya que tiene una referencia a él.

Por lo tanto, para reiterar, el "símbolo operativo" aquí no es *&, esa combinación en sí misma no significa mucho. El * es parte del tipo myStruct *, es decir, "puntero a myStruct", y el & lo hace una referencia, por lo que lo leería como "out es una referencia a un puntero a myStruct".

El programador original podría haber ayudado, en mi opinión, escribiéndolo como:

void myFunc(myStruct * &out) 

o incluso (no es mi estilo personal, pero, por supuesto, sigue siendo válida):

void myFunc(myStruct* &out) 

De Por supuesto, hay muchas otras opiniones sobre el estilo. :)

+0

"... como cualquier otro y antes de un nombre en C++ ..." es un poco descuidado. (Cuando así lo dice, también podría ser el operador de la dirección). Aún así, buena respuesta. +1 – sbi

+0

@sbi: De acuerdo, lo cambié ... Ahora bien, tal vez sea un poco autorreferencial. – unwind

+0

Mejor ahora, espero. :) Un poco académico, ya que la respuesta de Adriaan ha sido aceptada. – unwind

2

En C++ es una referencia a un puntero, más o menos equivalente a un puntero a puntero en C, por lo que el argumento de la función es asignable.

13

En C y C++, & significa llamar por referencia; permite que la función cambie la variable. En este caso, su variable es un puntero al tipo myStruct. En este caso, la función asigna un nuevo bloque de memoria y lo asigna a su puntero 'datos'.

En el pasado (digamos K & R) esto tenía que hacerse pasando un puntero, en este caso un puntero-a-puntero o **. El operador de referencia permite un código más legible y una verificación de tipo más sólida.

1

MiClase * & MyObject

Aquí es MiObjeto referencia a un puntero de MiClase. Entonces, al llamar a myFunction (MyClass * & MyObject) se llama por referencia, podemos cambiar MyObject que es referencia a un puntero. Pero si hacemos myFunction (MyClass * MyObject) no podemos cambiar MyObject porque es call by value, simplemente copiará la dirección en una variable temporal para que podamos cambiar el valor donde MyObject es Pointing pero no de MyObject.

por lo que en este caso el escritor está asignando primero un nuevo valor a out por eso es necesario llamar por referencia.

6

Parece que está implementando de nuevo un constructor.

¿Por qué no crear el constructor apropiado?
Nota en C++ una estructura es como una clase (puede tener un constructor).

struct myStruct 
{ 
    myStruct() 
     :field1(1) 
     ,field2(2) 
    {} 
}; 

myStruct* data1 = new myStruct; 

// or Preferably use a smart pointer 
std::auto_ptr<myStruct> data2(new myStruct); 

// or a normal object 
myStruct data3; 
+0

De hecho, estaba volviendo a implementar un constructor. ¡Gracias por el consejo! – bastibe

2

Al igual que con la mayoría de los tipos de datos en C++, puede leerlo de derecha a izquierda y tendrá sentido.

myStruct *&out 

out es una referencia (&) a un puntero (*) a un objeto de myStruct. Debe ser una referencia porque quiere cambiar lo que apunta a out (en este caso, un new myStruct).

6

Puede valer la pena explicar por qué no es &*, sino al revés. La razón es, las declaraciones se construyen de forma recursiva, y así una referencia a un puntero se acumula como

& out // reference to ... 
* (& out) // reference to pointer 

Los paréntesis se dejan caer, ya que son redundantes, sino que puede ayudar a ver el patrón. (Para ver por qué son redundantes, imagine cómo se ve la cosa en las expresiones, y notará que primero se toma la dirección, y luego se desreferencia - ese es el orden que queremos y que los paréntesis no cambiarán). Si cambia el orden, obtendrá

* out // pointer to ... 
& (* out) // pointer to reference 

El puntero a referencia no es legal. Es por eso que el orden es *&, que significa "referencia al puntero".

3

Como han dicho otros, el & significa que está tomando como referencia una variable real en la función en lugar de una copia de la misma. Esto significa que cualquier modificación hecha a la variable en la función afecta la variable original. Esto puede ser especialmente confuso cuando pasas un puntero, que ya es una referencia a otra cosa. En el caso de que su firma de la función se veía así

void myFunc(myStruct *out); 

¿Qué pasaría es que su función se aprobó una copia del puntero a trabajar. Eso significa que el puntero apuntaría a la misma cosa, pero sería una variable diferente. Aquí, cualquier modificación realizada en *out (es decir, en qué puntos de salida) sería permanente, pero los cambios realizados en out (el puntero en sí) solo se aplicarían dentro de myFunc. Con la firma como esta

void myFunc(myStruct *&out); 

Usted está declarando que la función se llevará una referencia a la original del puntero. Ahora los cambios realizados a la variable puntero out afectarán el puntero original que fue aprobada en.

Dicho esto, la línea

out = new myStruct; 

está modificando la variable puntero out y no *out.Lo que out solía apuntar sigue vivo y bien, pero ahora se ha creado una nueva instancia de myStruct en el montón, y out se ha modificado para apuntar a él.

Cuestiones relacionadas