Passando uma matriz por referência

184

Como funciona a passagem de uma matriz alocada estaticamente por referência?

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

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

Tem (&myArray)[100]algum significado ou é apenas uma sintaxe para passar qualquer matriz por referência? Eu não entendo parênteses separados seguidos por grandes colchetes aqui. Obrigado.

John DB
fonte
Existe alguma relação Rvalue para Lvalue com os parâmetros de função?
John DB

Respostas:

228

É uma sintaxe para referências de matriz - você precisa (&array)esclarecer ao compilador que deseja uma referência a uma matriz, em vez da matriz (inválida) de referências int & array[100];.

EDIT: Alguns esclarecimentos.

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

Essas três são maneiras diferentes de declarar a mesma função. Eles são todos tratados como int *parâmetros, você pode passar qualquer tamanho de matriz para eles.

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

Isso aceita apenas matrizes de 100 números inteiros. Você pode usar com segurança sizeofemx

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

Isso é analisado como uma "matriz de referências" - o que não é legal.

Erik
fonte
Por que não podemos ter uma variedade de referências, por exemplo int a, b, c; int arr[3] = {a, b, c};?
Vorac
4
Aha, descobri o porquê .
Vorac
2
Alguém poderia explicar por que void foo(int & x[100]);é analisado como "matriz de referências", por favor? É porque a regra "da direita para a esquerda"? Se sim, parece não ser consistente com o modo como void foo(int (&x)[100]);é analisado como "uma referência a uma matriz". Desde já, obrigado.
Zl9394
3
Não é da direita para a esquerda, é de dentro para fora e [] se liga mais firmemente que &.
Philipxy #
48

É apenas a sintaxe necessária:

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

^ Passe um array de 100 intpor referência, o nome dos parâmetros é myArray;

void Func(int* myArray)

^ Passe uma matriz. A matriz deteriora para um ponteiro. Assim, você perde informações de tamanho.

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

^ Passe um ponteiro de função. A função retorna inte leva a double. O nome do parâmetro é myFunc.

Martin York
fonte
Como passamos uma matriz de tamanho variável como referência?
Shivam Arora
@ShivamArora Você molda a função e transforma o tamanho em um parâmetro de modelo.
Martin York
24

É uma sintaxe. Nos argumentos da função, int (&myArray)[100]parênteses que envolvem o &myArraysão necessários. se você não usá-los, passará um array of referencese isso ocorre porque o subscript operator []arquivo tem maior precedência sobre o arquivo & operator.

Por exemplo int &myArray[100] // array of references

Portanto, usando type construction ()você diz ao compilador que deseja uma referência a uma matriz de 100 números inteiros.

Por exemplo int (&myArray)[100] // reference of an array of 100 ints

cpx
fonte
"se você não usá-los, passará um array of references" - o que, é claro, não pode existir, então você receberá um erro de compilação. É divertido para mim que as regras de precedência do operador insistem que isso deve acontecer por padrão de qualquer maneira.
Underscore_d
Existe mais algum tutorial sobre o tipo construction ()?
Chief Shifter
Obrigado, eu precisava de uma explicação que incluísse o motivo da precedência do operador, o que dá uma ideia do motivo pelo qual isso deve ser feito dessa maneira.
Cram2208 7/11
4

Matrizes são passadas por ponteiros por padrão. Você pode tentar modificar uma matriz dentro de uma chamada de função para entender melhor.

Eduardo A. Fernández Díaz
fonte
2
Matrizes não podem ser passadas por valor. Se a função recebe um ponteiro, uma matriz decai para um ponteiro para seu primeiro elemento. Não tenho certeza do que você está tentando dizer aqui.
Ulrich Eckhardt
@UlrichEckhardt Estou tentando dizer que "Matrizes não podem ser passados por valor", como você disse antes, eles são padrão passados por referência
Eduardo A. Fernández Díaz
8
A matriz não é passada por valor nem por referência. Eles são passados ​​por ponteiros. Se matrizes são passadas por referência por padrão, você não terá problemas ao usar sizeof nelas. Mas esse não é o caso. Matrizes decaem para ponteiros quando passadas para uma função.
User3437460
2
As matrizes podem ser passadas por referência OU degradando para um ponteiro. Por exemplo, usando char arr[1]; foo(char arr[])., arr é degradado em um ponteiro; enquanto estiver usando char arr[1]; foo(char (&arr)[1]), arr é passado como referência. É notável que a forma anterior seja frequentemente considerada mal formada, pois a dimensão está perdida.
Zl9394
Re, "Matrizes são ... passadas por ponteiros". Essa descrição parece pouco convencional, na melhor das hipóteses, e pode ser confusa para iniciantes. O nome de uma variável da matriz é uma expressão válida cujo valor é um ponteiro para o primeiro membro da matriz. Se você tem alguma função foo(T* t)e tem uma matriz T a[N];, quando escreve foo(a);, acho que seria mais correto dizer que você está passando um ponteiro, não passando uma matriz e passando o ponteiro por valor.
Solomon Slow
1

A seguir, cria-se uma função genérica, utilizando como referência uma matriz de qualquer tamanho e tipo:

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

brinque com o código.

Usuário12547645
fonte