web-dev-qa-db-fra.com

Utilisation de l'opérateur & dans les signatures de fonctions C++

Je suis en train de lire le C++ accéléré et je me suis rendu compte que je ne comprenais pas vraiment comment et fonctionne dans les signatures de fonction. 

int* ptr=#

signifie que ptr contient maintenant l'adresse num, mais qu'est-ce que cela signifie?

void DoSomething(string& str)

de ce que je comprends, c’est un passage par référence d’une variable (c’est-à-dire en passant l’adresse) mais quand je le fais

void DoSomething(string& str)
{
  string copy=str;
}

ce qu'il crée est une copie de str. Ce que je pensais que cela ferait serait de générer une erreur puisque j'essaie d'attribuer un pointeur à une variable.

Que se passe-t-il ici? Et quel est le sens de l'utilisation des appels de fonction * et & in?

20
Ziv

Une référence est pas un pointeur, ils sont différents bien qu’ils servent un but similaire . Vous pouvez considérer une référence comme un alias d’une autre variable, c’est-à-dire que la seconde variable a la même adresse. Il ne contient pas l'adresse elle-même, il se contente de references la même portion de mémoire que la variable à partir de laquelle elle a été initialisée.

Alors 

string s = "Hello, wordl";
string* p = &s; // Here you get an address of s
string& r = s; // Here, r is a reference to s    

s = "Hello, world"; // corrected
assert( s == *p ); // this should be familiar to you, dereferencing a pointer
assert( s == r ); // this will always be true, they are twins, or the same thing rather

string copy1 = *p; // this is to make a copy using a pointer
string copy = r; // this is what you saw, hope now you understand it better.
33
unkulunkulu

Le caractère & en C++ a un double objectif. Cela peut signifier (au moins)

  1. Prendre l'adresse d'une valeur
  2. Déclarer une référence à un type

L’utilisation à laquelle vous faites référence dans la signature de fonction est une instance de # 2. Le paramètre string& str est une référence à une instance string. Cela ne se limite pas aux signatures de fonctions, cela peut également se produire dans les corps de méthodes.

void Example() {
  string s1 = "example";
  string& s2 = s1;  // s2 is now a reference to s1
}

Je recommanderais de vérifier l'entrée C++ FAQ sur les références, car c'est une bonne introduction. 

23
JaredPar

Vous ne devriez pas savoir rien à propos des pointeurs tant que vous n’êtes pas passé au chapitre 10 de C++ accéléré!

Une référence crée un autre nom, un alias, pour quelque chose qui existe ailleurs. C'est tout. Il n'y a aucun pointeur ou adresse caché impliqué. Ne regarde pas derrière le rideau!

Pensez à un gars nommé Robert

guy   Robert;

Parfois, vous voudrez peut-être l'appeler Bob

guy& Bob = Robert;

Maintenant, Bob et Robert se réfèrent tous deux au même gars. Vous ne recevez pas son adresse (ni son numéro de téléphone), mais simplement un autre nom pour la même chose.

Dans votre fonction

void DoSomething(string& str)
{
  string copy=str;
}

cela fonctionne exactement de la même manière, str est un autre nom pour une chaîne qui existe ailleurs.

Ne vous inquiétez pas de la façon dont cela se produit, pensez simplement à une référence comme à un nom d'objet ... Le compilateur doit trouver un moyen de relier les noms, ce que vous n'avez pas à faire.

12
Bo Persson

Dans le cas de l'affectation de variables (c.-à-d. int* ptr = &value), l'utilisation de l'esperluette retournera l'adresse address de votre variable (dans ce cas, l'adresse de value).

Dans les paramètres de fonction, utiliser l'esperluette signifie que vous passez l'accès, ou la référence, à la même zone physique en mémoire de la variable (si vous ne l'utilisez pas, une copie est envoyée à la place). Si vous utilisez un astérisque dans le paramètre, vous indiquez que vous passez un pointeur de variable, ce qui donnera presque le même résultat. La différence ici est que, avec une esperluette, vous aurez un accès direct à la variable via le nom, mais si vous passez un pointeur, vous devrez déférencer ce pointeur pour obtenir et manipuler la valeur réelle:

void increase1(int &value) {
   value++;
}

void increase2(int *value) {
   (*value)++;
} 

void increase3(int value) {
   value++;
}

Notez que increase3 ne fait rien à la valeur d'origine que vous transmettez car seule une copie est envoyée:

int main() {
   int number = 5;
   increase1(number);
   increase2(&number);
   increase3(number);
   return 0;
}

La valeur de number à la fin des 3 appels de fonction est 7, pas 8.

10
Manny D

C'est une référence qui permet à la fonction de modifier la chaîne passée, contrairement à un paramètre de chaîne normal où la modification n'affecterait pas la chaîne transmise à la fonction.

Vous verrez souvent un paramètre de type const string & qui est effectué à des fins de performances, car une référence interne ne crée pas de copie de la chaîne.

4
pezcode
int* ptr=#

1er cas: ptr étant une mémoire, il stocke l'adresse d'une variable. L'opérateur & renvoie l'adresse de num en mémoire.

void DoSomething(string& str)

2ème cas: l'opérateur esperluette est utilisé pour montrer que la variable est passée par référence et peut être modifiée par la fonction.

Donc, fondamentalement, l'opérateur & a 2 fonctions en fonction du contexte.

2
Pepe

Bien que passer par référence puisse être implémenté par le compilateur en transmettant l'adresse sous forme de pointeur, cela n'a sémantiquement rien à voir avec les adresses ou les pointeurs. en termes simples, il s’agit simplement d’un alias pour une variable. 

C++ a de nombreux cas où la syntaxe est réutilisée dans différents contextes avec différentes sémantiques, et c'est l'un de ces cas.

1
jk.

Dans le cas de:

int* ptr=#

vous déclarez une variable nommée ptr avec le type d'un int * (pointeur int) et définissez sa valeur sur "l'adresse de la variable num" (&num). L'opérateur "addressof" (&) renvoie un pointeur.

Dans le cas de:

void DoSomething(string& str)

vous déclarez que le premier paramètre de la méthode DoSomething () est de type "reference to string". En pratique, il s’agit de la méthode C++ pour définir "passe par référence".

Notez que, bien que l'opérateur & opèrede manière similairedans ce cas, il n'agit pas de la même manière. En particulier, lorsqu'il est utilisé en tant qu'opérateur, vous indiquez au compilateur de prendre l'adresse de la variable spécifiée; lorsqu'il est utilisé dans une signature de méthode, vous indiquez au compilateur que l'argument est une référence. Et notez également que le bit "argument en tant que référence" est différent d'avoir un argument qui est un pointeur; l'argument de référence (&) est déréférencé automatiquement et il n'y a aucune exposition à la méthode quant à l'emplacement de stockage des données sous-jacentes; avec un argument de pointeur, vous passez toujours par référence, mais vous vous exposez à la méthode dans laquelle la variable est stockée et vous exposez potentiellement des problèmes si la méthode ne parvient pas à effectuer une déréférence (ce qui se produit plus souvent que vous ne le pensiez).

1
Paul Sonier

Vous copiez de manière inexpliquée copy à partir de str. Oui, str est une référence, mais cela ne signifie pas que vous ne pouvez pas en construire un autre. En c ++, l'opérateur & signifie l'une des 3 choses suivantes:

  1. Lorsque vous définissez une référence normale variable, vous créez un alias pour un objet.
  2. Lorsque vous l'utilisez dans un paramètre de fonction, il est transmis par référence - vous créez également un alias d'un objet, par opposition à une copie. Vous ne remarquez aucune différence dans ce cas, car il s'agit essentiellement de est l'objet que vous lui avez transmis. Cela fait fait une différence lorsque les objets que vous passez contiennent des pointeurs, etc.
  3. La dernière signification (et la plupart du temps sans rapport avec votre cas) de & est le bit AND.

Une autre façon de penser à une référence (bien que légèrement incorrecte) est d'utiliser le sucre syntaxique pour un pointeur déréférencé.

0
Seb Holzapfel