Références lvalue (C++)

De RAD Studio
Aller à : navigation, rechercher

Remonter à Spécificités du C++ - Index


En langage de programmation C, les arguments peuvent être passés uniquement par valeur. En C++, ce passage peut s'effectuer aussi bien par valeur que par référence. Les types de référence en C++ sont très proches des types de pointeur. Ils créent des alias pour des objets.

Remarque : Le référencement et le déréférencement de pointeurs spécifiques au C++ sont présentés dans Opérateurs de référencement/déréférencement.

L'opérateur & est utilisé pour créer des références lvalue :

int  i = 0;
int &ir = i; /* ir est un alias pour i */
ir = 2; /* même effet que i = 2 */

Ceci crée la lvalue ir comme un alias pour i, à condition que la valeur d'initialisation ait le même type que la référence. Toutes les opérations sur ir ont exactement le même effet que des opérations sur i. Par exemple, ir = 2 affecte la valeur 2 à i, et &ir renvoie l'adresse de i.

Arguments de référence

Le déclarateur de référence peut aussi être utilisé pour déclarer des paramètres de type référence dans une fonction :

void func1 (int i);
void func2 (int &ir);   // ir est du type "référence à int"

// ...
int sum = 3;
func1(sum);             // somme passée par valeur
func2(sum);             // somme passée par référence

L'argument sum transmis par référence est modifiable directement par func2. En revanche, func1 fournit une copie de l'argument sum (passé par valeur), de sorte que sum lui-même ne peut pas être modifié par func1.

Lorsqu'un argument réel x est transmis par valeur, l'argument formel correspondant dans la fonction reçoit une copie de x. Toute modification de cette copie dans le corps de la fonction n'est pas répercutée sur la valeur de x en dehors de la portée de la fonction. Naturellement, la fonction peut renvoyer une valeur qui sera ultérieurement utilisable pour modifier x, mais elle ne peut pas directement changer un paramètre passé par valeur.

En C, la modification de la valeur d'un paramètre d'une fonction en dehors de la portée de celle-ci suppose que vous transmettiez l'adresse du paramètre. Celle-ci est transmise par valeur, si bien que la modification du contenu de l'adresse affecte la valeur du paramètre en dehors de la portée de la fonction.

Même si la fonction n'a pas besoin de changer la valeur d'un paramètre, il demeure utile de transmettre l'adresse (ou une référence) à une fonction. Cela est notamment le cas si le paramètre est une structure de données ou un objet volumineux. La transmission d'un objet directement à une fonction nécessite de copier la totalité de l'objet.

Comparez les trois implémentations de la fonction treble :

#1 #2 #3
int treble_1(int n)
{
    return 3 * n;
}

// ...
int x, i = 4;
x = treble_1(i);
/* à présent x = 12, i = 4 */
void treble_2(int* np)
{
    *np = (*np) * 3;
}

// ...
treble_2(&i);
/* à présent i = 2 */
void treble_3(int &n/* n est un type référence */)
{
    n = n * 3;
}

// ...
treble_3(i);
/* à présent i = 36 */

La déclaration de l'argument formel type& t établit t comme type de "référence à type". Ainsi, lorsque treble_3 est appelé avec l'argument réel i, i est utilisé pour initialiser l'argument formel de référence n. n constitue donc un alias de i, de sorte que n = n*3; affecte aussi 3 * i à i.

Si l'initialiseur est une constante ou un objet d'un autre type que référence, un objet temporaire pour lequel la référence joue le rôle d'un alias est créé :

int& ir = 6; /* l'objet int temporaire créé, avec pour alias ir, prend la valeur 6 */
float f;
int& ir2 = f; /* crée un objet int temporaire avec ir2 pour alias ;
                      f converted before assignment */
ir2 = 2.0; /* à présent ir2 = 2, mais f ne change pas *

La création automatique d'objets temporaires permet la conversion de types référence lorsque les arguments réels et formels ont des types différents mais compatibles pour l'affectation. Lors du passage par valeur, naturellement, quelques problèmes de conversion se manifestent puisque la copie de l'argument réel peut être physiquement modifiée avant affectation à l'argument formel.

Voir aussi