Passer un tableau par référence

184

Comment fonctionne le passage d'un tableau alloué statiquement par référence?

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

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

At (&myArray)[100]-il une signification ou est-ce juste une syntaxe pour passer un tableau par référence? Je ne comprends pas les parenthèses séparées suivies de grands crochets ici. Merci.

John DB
la source
Existe-t-il une relation Rvalue à Lvalue avec les paramètres de la fonction?
John DB

Réponses:

228

C'est une syntaxe pour les références de tableau - vous devez l'utiliser (&array)pour clarifier au compilateur que vous voulez une référence à un tableau, plutôt que le tableau (invalide) de références int & array[100];.

EDIT: Quelques éclaircissements.

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

Ces trois méthodes sont différentes pour déclarer la même fonction. Ils sont tous traités comme prenant un int *paramètre, vous pouvez leur passer n'importe quel tableau de taille.

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

Cela n'accepte que les tableaux de 100 entiers. Vous pouvez utiliser en toute sécurité sizeofsurx

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

Ceci est analysé comme un "tableau de références" - ce qui n'est pas légal.

Erik
la source
Pourquoi ne pouvons-nous pas avoir un tableau de références par exemple int a, b, c; int arr[3] = {a, b, c};?
Vorac le
4
Aha, j'ai découvert pourquoi .
Vorac
2
Quelqu'un pourrait-il expliquer pourquoi void foo(int & x[100]);est analysé comme "tableau de références" s'il vous plaît? Est-ce à cause de la règle «de droite à gauche»? Si oui, cela ne semble pas cohérent avec la façon dont void foo(int (&x)[100]);est analysée comme "une référence à un tableau". Merci d'avance.
zl9394
3
Ce n'est pas de droite à gauche, c'est à l'envers et [] se lie plus étroitement que &.
philipxy
48

C'est juste la syntaxe requise:

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

^ Passez un tableau de 100 intpar référence, le nom des paramètres est myArray;

void Func(int* myArray)

^ Passez un tableau. Le tableau se désintègre en un pointeur. Ainsi, vous perdez des informations de taille.

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

^ Passez un pointeur de fonction. La fonction renvoie un intet prend un double. Le nom du paramètre est myFunc.

Martin York
la source
Comment passer un tableau de taille variable comme référence?
Shivam Arora
@ShivamArora Vous modélisez la fonction et faites de la taille un paramètre de modèle.
Martin York
24

C'est une syntaxe. Dans la fonction, les arguments int (&myArray)[100]entre parenthèses qui entourent le &myArraysont nécessaires. si vous ne les utilisez pas, vous passerez un array of referenceset c'est parce que le subscript operator []a une priorité plus élevée sur le & operator.

Par exemple int &myArray[100] // array of references

Ainsi, en utilisant, type construction ()vous indiquez au compilateur que vous voulez une référence à un tableau de 100 entiers.

Par exemple int (&myArray)[100] // reference of an array of 100 ints

cpx
la source
"si vous ne les utilisez pas, vous passerez un array of references" - qui, bien sûr, ne peut pas exister, donc vous obtiendrez une erreur de compilation. C'est amusant pour moi que les règles de priorité des opérateurs insistent sur le fait que cela doit se produire par défaut de toute façon.
underscore_d
Y a-t-il plus de tutoriel sur la construction de type ()?
Chief Shifter
Merci, j'avais besoin d'une explication qui comprenait la raison de la priorité des opérateurs, ce qui donne un sens à la raison pour laquelle cela devrait être fait de cette façon.
cram2208
4

Les tableaux sont transmis par défaut par des pointeurs. Vous pouvez essayer de modifier un tableau dans un appel de fonction pour une meilleure compréhension.

Eduardo A. Fernández Díaz
la source
2
Les tableaux ne peuvent pas être passés par valeur. Si la fonction reçoit un pointeur, un tableau se désintègre en un pointeur vers son premier élément. Je ne suis pas sûr de ce que vous essayez de dire ici.
Ulrich Eckhardt
@UlrichEckhardt J'essaie de dire que "les tableaux ne peuvent pas être passés par valeur" comme vous l'avez dit auparavant, ils sont passés par défaut par référence
Eduardo A. Fernández Díaz
8
Les tableaux ne sont ni passés par valeur ni par référence. Ils sont passés par des pointeurs. Si les tableaux sont passés par référence par défaut, vous n'aurez aucun problème à utiliser sizeof sur eux. Mais ce n'est pas le cas. Les tableaux se désintègrent en pointeurs lorsqu'ils sont passés dans une fonction.
user3437460
2
Les tableaux peuvent être passés par référence OU en se dégradant en pointeur. Par exemple, en utilisant char arr[1]; foo(char arr[])., arr se dégrade en pointeur; lors de l'utilisation char arr[1]; foo(char (&arr)[1]), arr est passé comme référence. Il est à noter que l'ancienne forme est souvent considérée comme mal formée car la dimension est perdue.
zl9394
Re, "Les tableaux sont ... passés par des pointeurs." Cette description semble au mieux non conventionnelle et peut être déroutante pour les débutants. Le nom d'une variable de tableau, est une expression valide dont la valeur est un pointeur le premier membre du tableau. Si vous avez une fonction foo(T* t)et que vous avez un tableau, T a[N];lorsque vous écrivez, foo(a);je pense qu'il serait plus correct de dire que vous passez un pointeur, pas un tableau, et que vous passez le pointeur par valeur.
Solomon Slow
1

Ce qui suit crée une fonction générique, prenant un tableau de n'importe quelle taille et de n'importe quel type par référence:

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

jouer avec le code.

Utilisateur12547645
la source