Sont des vecteurs passés aux fonctions par valeur ou par référence en C ++


94

Je code en C ++. Si j'ai une fonction void foo(vector<int> test)et que je l'appelle dans mon programme, le vecteur sera-t-il passé par valeur ou référence? Je ne suis pas sûr parce que je sais que les vecteurs et les tableaux sont similaires et qu'une fonction comme celle- void bar(int test[])ci passerait le test par référence (pointeur?) Au lieu de par valeur. Je suppose que je devrais passer le vecteur par pointeur / référence explicitement si je voulais éviter de passer par valeur, mais je ne suis pas sûr.


5
C ++ a une sémantique de "passer par valeur", donc il est passé par valeur. Vous pouvez cependant décider de passer par référence. Le choix dépend vraiment de ce que fait la fonction.
juanchopanza

2
utiliser par référence, si la fonction que vous ne voulez pas changer le contenu du vecteur le rend constant, sinon passez-le simplement par référence. Cela évitera une copie
indésirable

3
De plus, une référence n'est pas un pointeur.
Le Croissant Paramagnétique

2
@AliKazmi Sauf si vous voulez une copie dans le corps de la fonction.
juanchopanza

Cela dépend de ce que vous voulez réaliser. L'utilisation de l'un des pointeurs intelligents standard est parfois utile, par exemple si vous souhaitez transmettre la propriété, utilisez unique_ptr. Mais généralement, je passe std :: vector par référence.
Erik Alapää

Réponses:


134

Si je devais deviner, je dirais que vous êtes d'origine Java. Il s'agit de C ++, et les choses sont passées par valeur sauf si vous spécifiez le contraire en utilisant &-operator (notez que cet opérateur est également utilisé comme opérateur 'address-of', mais dans un contexte différent). Tout cela est bien documenté, mais je vais quand même réitérer:

void foo(vector<int> bar); // by value
void foo(vector<int> &bar); // by reference (non-const, so modifiable inside foo)
void foo(vector<int> const &bar); // by const-reference

Vous pouvez également choisir de passer un pointeur sur un vecteur (void foo(vector<int> *bar) ), mais à moins que vous ne sachiez ce que vous faites et que vous estimiez que c'est vraiment la voie à suivre, ne le faites pas.

De plus, les vecteurs ne sont pas les mêmes que les tableaux! En interne, le vecteur garde la trace d'un tableau dont il gère la gestion de la mémoire pour vous, mais il en va de même pour de nombreux autres conteneurs STL. Vous ne pouvez pas passer un vecteur à une fonction qui attend un pointeur ou un tableau ou vice versa (vous pouvez accéder au (pointeur vers) le tableau sous-jacent et l'utiliser cependant). Les vecteurs sont des classes offrant beaucoup de fonctionnalités via ses fonctions membres, tandis que les pointeurs et les tableaux sont des types intégrés. De plus, les vecteurs sont alloués dynamiquement (ce qui signifie que la taille peut être déterminée et modifiée à l'exécution) tandis que les tableaux de style C sont alloués statiquement (sa taille est constante et doit être connue au moment de la compilation), ce qui limite leur utilisation.

Je vous suggère de lire un peu plus sur C ++ en général (en particulier la désintégration des tableaux ), puis de jeter un œil au programme suivant qui illustre la différence entre les tableaux et les pointeurs:

void foo1(int *arr) { cout << sizeof(arr) << '\n'; }
void foo2(int arr[]) { cout << sizeof(arr) << '\n'; }
void foo3(int arr[10]) { cout << sizeof(arr) << '\n'; }
void foo4(int (&arr)[10]) { cout << sizeof(arr) << '\n'; }

int main()
{
    int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    foo1(arr);
    foo2(arr);
    foo3(arr);
    foo4(arr);
}

2
Quelqu'un peut-il m'aider à comprendre la dernière fonction de déclaration foo4? Pourquoi renvoie-t-il la taille du tableau au lieu de la taille du pointeur comme dans d'autres fonctions?
abhishek_M

3
@abhishek_M car le type de paramètre est une référence. Une référence ne peut être liée qu'à une expression du même type. Pour cette raison, le tableau ne se décompose pas, car une référence à un tableau ne peut pas être liée à un pointeur, il ne peut être lié qu'à un tableau du même type (dans ce cas, un tableau de 10 entiers)
bolov

1
c ++ 11 a une "sémantique de déplacement" et vous pouvez le faire avec précaution et passer par valeur (avec une sémantique de déplacement) sans copie. Voici un lien qui m'a beaucoup aidé: mbevin.wordpress.com/2012/11/20/move-semantics
fchen

23

A vectorest fonctionnellement identique à un tableau. Mais, à la langue vectorest un type, et intest aussi un type. Pour un argument de fonction, un tableau de n'importe quel type (y compris vector[]) est traité comme un pointeur. A vector<int>n'est pas identique à int[](au compilateur). vector<int>est non-tableau, non-référence et non-pointeur - il est passé par valeur, et par conséquent, il appellera copy-constructor.

Donc, vous devez utiliser vector<int>&(de préférence avec const, si la fonction ne le modifie pas) pour le passer comme référence.


Quelle est la syntaxe pour passer un "tableau de vecteurs" par référence à une fonction?
ab123

void functionName (std :: vector <int> (& vc) [5]) {}
RIanGillis

9

void foo(vector<int> test)

vecteur serait passé par valeur dans ce.

Vous avez plus de façons de passer des vecteurs en fonction du contexte: -

1) Passer par référence: - Cela permettra à la fonction foo de changer votre contenu du vecteur. Plus efficace que le passage par valeur car la copie du vecteur est évitée.

2) Passer par const-reference: - C'est efficace et fiable quand vous ne voulez pas que la fonction change le contenu du vecteur.


1

lorsque nous passons vecteur par valeur dans une fonction en tant qu'argument, cela crée simplement la copie du vecteur et aucun effet ne se produit sur le vecteur défini dans la fonction principale lorsque nous appelons cette fonction particulière. tandis que lorsque nous passons le vecteur par référence tout ce qui est écrit dans cette fonction particulière, chaque action va s'exécuter sur le vecteur qui est défini dans la fonction principale ou une autre fonction lorsque nous appelons cette fonction particulière.

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.