Pasar una matriz por referencia

184

¿Cómo funciona pasar una matriz asignada estáticamente por referencia?

void foo(int (&myArray)[100])
{
}

int main()
{
    int a[100];
    foo(a);
}

¿ (&myArray)[100]Tiene algún significado o es solo una sintaxis para pasar cualquier matriz por referencia? No entiendo paréntesis separados seguidos de grandes corchetes aquí. Gracias.

John DB
fuente
¿Existe alguna relación de Rvalue a Lvalue con los parámetros de la función?
John DB

Respuestas:

228

Es una sintaxis para las referencias de matriz: debe usar (&array)para aclarar al compilador que desea una referencia a una matriz, en lugar de la matriz de referencias (no válida) int & array[100];.

EDITAR: Alguna aclaración.

void foo(int * x);
void foo(int x[100]);
void foo(int x[]);

Estas tres son formas diferentes de declarar la misma función. Todos se tratan como si tomaran un int *parámetro, puede pasarles cualquier tamaño de matriz.

void foo(int (&x)[100]);

Esto solo acepta matrices de 100 enteros. Puede usar con seguridad sizeofenx

void foo(int & x[100]); // error

Esto se analiza como un "conjunto de referencias", que no es legal.

Erik
fuente
¿Por qué no podemos tener una serie de referencias, por ejemplo int a, b, c; int arr[3] = {a, b, c};?
Vorac
44
Ajá, descubrí por qué .
Vorac
2
¿Podría alguien explicar por qué void foo(int & x[100]);se analiza como "conjunto de referencias" por favor? ¿Es porque la regla de "de derecha a izquierda"? En caso afirmativo, parece no ser coherente con la forma en que void foo(int (&x)[100]);se analiza como "una referencia a una matriz". Gracias por adelantado.
zl9394
3
No es de derecha a izquierda, está al revés y [] se une más fuerte que &.
Filipinas
48

Es solo la sintaxis requerida:

void Func(int (&myArray)[100])

^ Pase la matriz de 100 intpor referencia, el nombre del parámetro es myArray;

void Func(int* myArray)

^ Pase una matriz. La matriz se descompone en un puntero. Por lo tanto, pierde información sobre el tamaño.

void Func(int (*myFunc)(double))

^ Pase un puntero de función. La función devuelve an inty toma a double. El nombre del parámetro es myFunc.

Martin York
fuente
¿Cómo pasamos una matriz de tamaño variable como referencia?
Shivam Arora
@ShivamArora Puede personalizar la función y convertir el tamaño en un parámetro de plantilla.
Martin York
24

Es una sintaxis. En la función, los argumentos int (&myArray)[100]entre paréntesis que encierran &myArrayson necesarios. si no los usa, pasará un array of referencesy eso se debe a que subscript operator []tiene mayor prioridad sobre el & operator.

P.ej int &myArray[100] // array of references

Entonces, al usar, type construction ()le dice al compilador que desea una referencia a una matriz de 100 enteros.

P.ej int (&myArray)[100] // reference of an array of 100 ints

cpx
fuente
"si no los usa, pasará un array of references", que por supuesto no puede existir, por lo que obtendrá un error de compilación. Es divertido para mí que las reglas de precedencia del operador insistan en que esto debe suceder de manera predeterminada de todos modos.
underscore_d
¿Hay más tutoriales sobre construcción de tipos ()?
Chief Shifter
Gracias, necesitaba una explicación que incluyera la razón sobre la precedencia del operador, lo que da una idea de por qué debería hacerse de esta manera.
cram2208
4

Las matrices se pasan por defecto por punteros. Puede intentar modificar una matriz dentro de una llamada de función para una mejor comprensión.

Eduardo A. Fernández Díaz
fuente
2
Las matrices no se pueden pasar por valor. Si la función recibe un puntero, una matriz decae a un puntero a su primer elemento. No estoy seguro de lo que estás tratando de decir aquí.
Ulrich Eckhardt
@UlrichEckhardt Estoy tratando de decir que "Las matrices no se pueden pasar por valor" como dijiste antes, son pasadas por defecto por referencia
Eduardo A. Fernández Díaz
8
La matriz no se pasa por valor ni por referencia. Son pasados ​​por punteros. Si las matrices se pasan por referencia de forma predeterminada, no tendrá problemas para usar sizeof en ellas. Pero ese no es el caso. Las matrices decaen a punteros cuando pasan a una función.
user3437460
2
Las matrices se pueden pasar por referencia O degradando a un puntero. Por ejemplo, usando char arr[1]; foo(char arr[])., arr se degrada a un puntero; mientras se usa char arr[1]; foo(char (&arr)[1]), arr se pasa como referencia. Es notable que la forma anterior a menudo se considera mal formada ya que la dimensión se pierde.
zl9394
Re: "Las matrices son ... pasadas por punteros". Esa descripción suena poco convencional en el mejor de los casos, y puede ser confusa para los novatos. El nombre de una variable de matriz es una expresión válida cuyo valor es un puntero del primer miembro de la matriz. Si tiene alguna función foo(T* t)y tiene una matriz T a[N];, cuando escriba foo(a);, creo que sería más correcto decir que está pasando un puntero, no pasando una matriz, y está pasando el puntero por valor.
Solomon Slow
1

Lo siguiente crea una función genérica, tomando una matriz de cualquier tamaño y de cualquier tipo por referencia:

template<typename T, std::size_t S>
void my_func(T (&arr)[S]) {
   // do stuff
}

Juega con el código.

Usuario12547645
fuente