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.


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.


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.


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


"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.


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.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.