¿Cuáles son las distinciones entre los diversos símbolos (*, &, etc.) combinados con parámetros?

Posible duplicado:
c ++ * vs & in function declaration

Sé que esto probablemente parezca una pregunta increíblemente elemental para muchos de ustedes, pero realmente he tenido un tiempo imposible para encontrar una explicación buena y completa, a pesar de mi mejor búsqueda en Google. Estoy seguro de que la respuesta está ahí, por lo que mis términos de búsqueda deben ser terribles.

En C ++, una variedad de símbolos y combinaciones de los mismos se utilizan para marcar los parámetros (así como los argumentos para esos parámetros). ¿Cuáles son exactamente sus significados?

Ej .: ¿Cuál es la diferencia entre void func(int *var) y void func(int **var) ? ¿Qué pasa con int &var ?

La misma pregunta representa los tipos de devolución, así como los argumentos. ¿Qué significa int& func(int var) en comparación con int* func(int var) ? Y en argumentos, ¿cómo y = func(*x) difiere de y = func(&x) ?

Estoy más que feliz de leer volúmenes enormes sobre el tema si solo usted pudiera señalarme en la dirección correcta. Además, estoy muy familiarizado con los conceptos generales de progtwigción: OO, generics / plantillas, etc., pero no la notación utilizada en C / C ++.

EDITAR: Parece que he dado la impresión de que no sé qué son los indicadores. Me pregunto cómo podría ser eso 🙂

Entonces para una aclaración: entiendo perfectamente cómo funcionan los punteros. Lo que no estoy entendiendo, y soy extrañamente incapaz de encontrar respuestas, es el significado de, por ejemplo, ‘void func (int & var)’. En el caso de una instrucción de asignación, el operador ‘&’ estaría en el lado derecho, como en ‘int * x = & y;’, pero en lo anterior, el operador ‘&’ está efectivamente en el lado izquierdo. En otras palabras, está operando en el valor l, en lugar del valor r. Esto claramente no puede tener el mismo significado.

Espero que tenga más sentido ahora?

Para comprender esto, primero deberá comprender los indicadores y las referencias. Simplemente explicaré la syntax de la statement de tipo sobre la que está preguntando, suponiendo que ya sabe qué punteros y referencias existen.

En C, se dice que ‘la statement sigue al uso’. Eso significa que la syntax para declarar una variable imita el uso de la variable: generalmente en una statement tendrá un tipo de base como int o float seguido de algo que se parece a una expresión. Por ejemplo, en int *y el tipo de base es int y la expresión similar es *y . A partir de entonces, esa expresión evalúa a un valor con el tipo base dado.

Entonces int *y significa que luego una expresión *y es un int . Eso implica que y debe ser un puntero a un int. Lo mismo se aplica a los parámetros de función y, de hecho, a las declaraciones de funciones completas:

 int *foo(int **bar); 

En el int **bar , **bar es una int, implicando *bar es un puntero a un int, y la bar es un puntero a un puntero a un int. También declara que *foo(arg) será un int ( arg dado del tipo apropiado), lo que implica que foo(arg) da como resultado un puntero a un int.¹ Entonces la statement de la función completa dice “foo es una función que toma una puntero a un puntero a un int, y devolver un puntero a un int. ”

C ++ agrega el concepto de referencias y arruina un poco las declaraciones de estilo C en el proceso. Debido a que tomar la dirección de una variable usando el operador de dirección & debe dar como resultado un puntero, C no tiene ningún uso para las declaraciones & en; int &x significa &x es un int, lo que implica que x es un tipo en el que tomar la dirección de ese tipo da como resultado un int.² Entonces, debido a que esta syntax no se usa, C ++ la apropia para un propósito completamente diferente.

En C ++ int &x significa que x es una referencia a un int. El uso de la variable no involucra a ningún operador para ‘desreferenciar’ la referencia, por lo que no importa que el símbolo del declarante de referencia se oponga al operador de dirección de entrada. El mismo símbolo significa cosas completamente diferentes en los dos contextos, y nunca es necesario usar un significado en el contexto donde el otro está permitido.

Así que char &foo(int &a) declara una función tomando una referencia a un int y devolviendo una referencia a un char. func(&x) es una expresión que toma la dirección de x y la pasa a func .


1. De hecho, en la syntax C original para declarar funciones ‘declaraciones seguir uso’ se siguió aún más estrictamente. Por ejemplo, declararía una función como int foo(a,b) y los tipos de parámetros se declararon en otro lugar, de modo que la statement se vería exactamente como un uso, sin los tipos de letra adicionales.

2. Por supuesto int *&x; podría tener sentido en que *&x podría ser un int, pero C en realidad no hace eso.

Lo que está preguntando se llama punteros ( * ) y referencia a ( & ), que creo que se explica mejor aquí .

Los símbolos * y & tienen tres significados cada uno en C ++:

  1. Cuando se aplica a una expresión, significan “desreferencia” y “dirección de”, respectivamente, como usted sabe.

  2. Cuando forman parte de un tipo, significan “puntero” y “referencia”, respectivamente.

    Como a C ++ no le importa el espaciado arbitrario, la statement int *ptr es exactamente la misma que la statement int* ptr , en la que ahora puede ver más claramente que se trata de un objeto llamado ptr de tipo int* . 1

  3. Cuando se usan entre dos expresiones, significan “multiplicar” y “Y a nivel de bit”, respectivamente.


1 – aunque, frustrantemente, esta no es la forma en que la gramática interna lo lee, gracias al desagradable legado del sistema de tipos de C. Así que evite las declaraciones múltiples de una sola línea que involucren punteros a menos que desee una sorpresa.

Ejemplo: ¿Cuál es la diferencia entre ‘void func (int * var)’ y ‘void func (int ** var)’? ¿Qué pasa con ‘int & var’?

La misma pregunta representa los tipos de devolución, así como los argumentos. ¿Qué significa ‘int & func (int var)’, en comparación con ‘int * func (int var)’? Y en los argumentos, ¿cómo ‘y = func (* x)’ difiere de ‘y = func (& x)’?

 (1)    void func (int *var)  here int *var is a pointer to integer, ie it can point to an array or any buffer that should be handled with integer pointer arithmetic. In simple terms , var holds the address of the respective **actual parameter.** eg: int arr[10]; func(arr); int a = 33; func(&a); Here, &a means we are explicitly passing address of the the variable 'a'. (2) int m = 0; int &var = m; Here var means reference, ie it another alias name for variable 'm' , so any change 'var' makes will change the contents of variable 'm'. var = 2; /* will change the actual contents of 'm' */ This simple example will not make sense , unless you understand the context. Reference are usually use to pass parameter to function, so that changes made by the function to the passed variable is visible at the caller. int swap(int &m, int &n) { tmp = m; m = n; n = tmp; } void main( void ) { int x = 1, y = 2; swap(x, y); /* x = 2, y =1 */ } (3) 'int& func(int var)' mean, as compared to 'int* func(int var)'? int& func(int var) means the function returns a reference; int* func(int var) means the function returns a pointer / address; Both of the them has its context; int& setNext() { return next; } setNext() = previous; where as int* setNext() { return &next; } int *inptr; inptr = setNext(); *inptr = previous; In the previous two lines, int *inptr <- integer pointer declaration; *inptr <- means we are accessing contents of the address pointed by inptr; ie we are actually referring to 'next' variable. The actual use is context specific. It can't be generalized. (4) how does 'y = func(*x)' differ from 'y = func(&x)'? y = func(&x) is already explained. y = func(*x) , well i'm not sure if you actually meant *x. int swap(int *m, int *n) { tmp = *m; *m = *n; *n = tmp; } 

Los símbolos & y * se utilizan para indicar una referencia y un tipo de puntero, respectivamente.

int significa simplemente el tipo ‘int’, int* significa ‘puntero a int’, int& significa ‘referencia a int’,

Un puntero es una variable que se usa para almacenar la dirección de una variable. Una referencia tiene la syntax de su tipo base, pero la semántica de un puntero a ese tipo. Esto significa que no necesita desreferenciarlo para cambiar el valor.

Para tomar un ejemplo, los siguientes bloques de código son semánticamente equivalentes:

 int* a = &value; *a = 0; 

Y:

 int& a = value; a = 0; 

Las razones principales para usar punteros o referencias como tipo de argumento es evitar la copia de objetos y poder cambiar el valor de un argumento pasado. Ambas funcionan porque, cuando pasa por referencia, solo se copia la dirección, lo que le da acceso a la misma ubicación de memoria que “pasó” a la función.

Por el contrario, si no se utiliza un tipo de referencia o puntero, se realizará una copia completa del argumento, y esta copia estará disponible dentro de la función.