IdentifiantMot de passe
Loading...
Mot de passe oubli� ?Je m'inscris ! (gratuit)
logo

FAQ C++Consultez toutes les FAQ

Nombre d'auteurs : 34, nombre de questions : 368, derni�re mise � jour : 14 novembre 2021  Ajouter une question

 

Cette FAQ a �t� r�alis�e � partir des questions fr�quemment pos�es sur les forums de http://www.developpez.com et de l'exp�rience personnelle des auteurs.

Je tiens � souligner que cette FAQ ne garantit en aucun cas que les informations qu'elle propose sont correctes ; les auteurs font le maximum, mais l'erreur est humaine. Cette FAQ ne pr�tend pas non plus �tre compl�te. Si vous trouvez une erreur ou si vous souhaitez devenir r�dacteur, lisez ceci.

Sur ce, nous vous souhaitons une bonne lecture.

SommaireLes r�f�rences (6)
pr�c�dent sommaire suivant
 

Une r�f�rence est un alias, un nom alternatif pour un objet. Le principe � retenir est que tout se passe comme si c'�tait l'objet lui-m�me et non une r�f�rence sur lui.

Les r�f�rences sont souvent utilis�es lors du passage de param�tres, en particulier avec le mot-cl� const (r�f�rence constante : donc le param�tre pass� est non modifiable) afin de rendre l'appel � la fonction plus performant sur des objets volumineux. Sans le mot-cl� const l'usage d'une r�f�rence indique alors que le param�tre est modifi� par la fonction.

Code c++ : S�lectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// fonction qui �change i et j 
void swap(int& i, int& j) 
{ 
    int tmp = i; 
    i = j; 
    j = tmp; 
} 
  
int main() 
{ 
    int x = 1; 
    int y = 2; 
    swap( x, y ); 
    // x = 2, y = 1 
}
Dans cet exemple, i et j sont des alias pour x et y du main. En d'autres mots, i est x (pas un pointeur sur x, ni une copie, mais x lui-m�me). Tout ce qui est fait � x est fait � i et inversement.

Bon, maintenant, pensons aux r�f�rences du point de vue du programmeur. Au risque de provoquer la confusion en donnant une autre perspective voici comment les r�f�rences sont impl�ment�es en pratique. Au fond, une r�f�rence i vers un objet x est habituellement son adresse. Mais quand le programmeur fait un i++, le compilateur g�n�re du code qui incr�mente x. Typiquement, les bits d'adressage que le compilateur utilise pour acc�der � x sont inchang�s. Un programmeur C pensera qu'il s'agit du passage d'un pointeur, avec les variantes syntaxiques suivantes :
  • D�placer le & de l'appelant � l'appel� ;
  • Supprimer les notations *s.

En d'autres mots, un programmeur le consid�rera comme une macro pour (*p), o� p est un pointeur sur x (par ex., le compilateur d�r�f�rencerait automatiquement le pointeur : i++ serait transform� en (*p)++).

Note : m�me si une r�f�rence est souvent impl�ment�e en utilisant une adresse dans le langage d'assemblage g�n�r�, ne consid�rez pas les r�f�rences comme un pointeur � marrant � sur un objet. Une r�f�rence est l'objet. Ce n'est pas un pointeur sur l'objet, ni une copie de l'objet. C'est l'objet.

Mis � jour le 19 octobre 2004 Aurelien.Regat-Barrel

L'�tat du r�f�rent (le r�f�rent est l'objet auquel la r�f�rence se rapporte) est modifi�.

Le r�f�rent est la r�f�rence, donc toute modification faite � la r�f�rence est faite au r�f�rent. Au niveau du compilateur, une r�f�rence est une � lvalue �, c'est-�-dire qu'il peut appara�tre � la gauche d'un op�rateur d'affectation.

Mis � jour le 19 octobre 2004 Cline

L'appel de fonction peut se trouver � la gauche d'un op�rateur d'assignation.

Cette possibilit� peut sembler �trange au premier abord. Par exemple, personne ne penserait que l'expression f() = 7; ait un sens. Par contre, si a est un objet de la classe Array, la plupart des gens trouveront que a[i] = 7; a un sens, m�me si a n'est qu'un appel de fonction cach� (c'est en fait l'appel de l'op�rateur Array::operator [](int), qui est l'op�rateur d'indexation de la classe Array)

Code C++ : S�lectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Array { 
public: 
    int size() const; 
    float& operator[] (int index); 
    ... 
}; 
  
int main() 
{ 
    Array a; 
    for (int i = 0; i < a.size(); ++i) 
        a[i] = 7;    // cette ligne appelle Array::operator[](int) 
    ... 
}

Mis � jour le 10 f�vrier 2004 Cline

Ce n'est pas possible.

On ne peut pas s�parer le r�f�r� de sa r�f�rence.

Contrairement aux pointeurs, lorsqu'une r�f�rence est li�e � un objet, elle ne peut pas �tre r�affect�e � un autre objet. La r�f�rence en elle-m�me n'est pas un objet (elle n'a pas d'identit� : prendre l'adresse d'une r�f�rence retourne l'adresse du r�f�rent).

De ce point de vue, une r�f�rence est similaire � un pointeur constant

Code c++ : S�lectionner tout
int* const p

par opposition � un pointeur sur une constante

Code c++ : S�lectionner tout
const int* p

En d�pit d'une certaine ressemblance, ne confondez pas les r�f�rences et les pointeurs ; ce n'est pas du tout la m�me chose.

Mis � jour le 10 f�vrier 2004 Cline

Lorsque l'on compare le code ex�cutable g�n�r� lors de l'utilisation d'un pointeur et celui g�n�r� lors de l'utilisation d'une r�f�rence, on remarque qu'il est strictement identique.

Cependant la r�f�rence a l'�norme avantage sur le pointeur d'apporter une garantie de non nullit�, et de respecter la constance.

De plus, on ne peut envisager de d�clarer une r�f�rence qu'en lui indiquant directement l'objet dont elle se fait l'alias.
Ainsi, alors que Type * ptr; sera accept�, Type & ref; sera refus�.
De plus, lorsque, dans une fonction, on r�cup�re un pointeur, on n'est pas toujours (rarement�?) assur� que ce pointeur est non NULL, il va donc falloir souvent le v�rifier par un

Code c++ : S�lectionner tout
if (mon_pointeur!=NULL) {...}
Alors que lorsque l'on re�oit une r�f�rence, on est assur� que l'objet a �t� instanci� du seul fait de cette clause de non nullit� et que l'on n'a donc pas besoin de le tester. Les r�f�rences assurent ainsi une pr�condition statique de l'appelant envers la fonction appel�e.

Non seulement, cela all�ge et simplifie le code, mais �galement il arrive que ce test suppl�mentaire p�se lourd en terme de vitesse d'ex�cution.

En ce qui concerne la constance, elle va s'appliquer, pour les pointeurs, diff�remment en fonction de l'endroit o� se trouve le mot cl� const voir Comment se g�re la constance avec les pointeurs? alors qu'avec une r�f�rence, les choses sont claires�: si une r�f�rence est d�clar�e constante, cela signifie�:
  • que l'on ne peut pas modifier l'objet ;
  • que l'on ne peut pas d�cider de se servir de la r�f�rence comme alias pour un autre objet.

En outre, il faut se souvenir que l'utilisation des pointeurs est �norm�ment associ�e � la gestion dynamique de la m�moire (cr�ation avec new ou new[] et destruction respectivement avec delete ou delete[]), et que la gestion dynamique de la m�moire est le champs de mines par excellence qu'il s'agit d'�viter autant que possible. Voir Quels sont les dangers li�s � l'utilisation des pointeurs�?

Or, il faut comprendre que le C++ fournit, au travers des diff�rents conteneurs qu'il pr�sente ou au travers de sa classe string, tout ce qu'il faut pour �viter � l'utilisateur de g�rer dynamiquement la m�moire si ce n'est pas tout � fait indispensable (cf Quel conteneur choisir pour stocker mes objets ?).

Enfin, m�me si ce n'est qu'un d�tail, il faut avouer que le fait de garder exactement la m�me syntaxe lorsque l'on manipule une r�f�rence que lorsque l'on manipule l'objet lui-m�me est presque rassurant.

En conclusion, l'id�al en C++ sera toujours de manipuler des r�f�rences (�ventuellement constantes) partout o� c'est possible sans devoir avoir recours � l'op�rateur � & � (prendre l'adresse de) et de ne manipuler des pointeurs que lorsque l'on n'a vraiment pas le choix.

Les cas pour lesquels nous n'aurons pas le choix �tant�:
  • Lorsqu'il s'agit de passer un argument optionnel ou pouvant ne pas exister, on passe alors un pointeur NULL�;
  • Lorsqu'il s'agit d'avoir une r�f�rence vers un objet optionnel ou pouvant ne pas exister (on utilise alors un pointeur sur l'objet dont l'adresse initialis�e est NULL)�;
  • Lorsque tu as besoin de cr�er un objet polymorphique et que le type de l'objet � cr�er se d�termine selon les circonstances�;
  • Lorsque, confront� � une relation � conteneur � contenu �, le contenu doit disposer d'une r�f�rence sur le conteneur�;
  • Lorsque l'on souhaitera pouvoir modifier l'objet auquel on se r�f�re.

Note : il existe Boost.Optional permettant de manipuler des objets comme s'ils n'�taient pas initialis�s.

Note : malgr� la garantie qu'une r�f�rence ne soit pas nulle, il existe des cas o� elle peut r�f�rer � un objet qui a �t� d�truit ou d�plac�, son utilisation �tant d�s lors dangereuse. On pourra citer le cas du retour par r�f�rence d'un objet local :
Code c++ : S�lectionner tout
1
2
3
4
5
Type& fonction() 
{ 
    Type tmp; 
    return tmp; 
} // tmp est d�truit
signal� par le compilateur par le message :
reference to a local variable 'tmp' returned

mais il existe des cas moins triviaux qui ne seront pas signal�s.

Mis � jour le 6 juillet 2014 3DArchi koala01 Luc Hermitte r0d

Le terme handle est utilis� pour d�signer n'importe quelle technique qui permet de manipuler un autre objet (un genre de pseudo pointeur g�n�ralis�). Ce terme est (volontairement) ambigu et peu pr�cis.

L'ambigu�t� est un avantage dans certains cas. Par exemple, au tout d�but du design vous ne serez peut-�tre pas pr�t � adopter une repr�sentation sp�cifique pour d�signer les handles. Vous ne serez peut-�tre pas s�r du choix � faire entre les simples pointeurs, les r�f�rences, les pointeurs de pointeurs, les r�f�rences de pointeurs, ou encore des tableaux indic�s, ou des tables de hachage, ou des bases de donn�es ou n'importe quelle autre technique. Si vous savez que vous aurez besoin de quelque chose qui identifiera de fa�on unique un objet, appelez cette chose un handle.

Si votre but final est de permettre � une portion de code d'identifier/rechercher un objet sp�cifique d'une classe d'un certain type (par ex. Fred), vous devrez passer un handle sur Fred � cette portion de code. Le handle peut �tre une cha�ne qui peut-�tre utilis�e comme une cl� dans une table de recherche bien connue. Par exemple, une cl� dans

Code c++ : S�lectionner tout
std::map<std::string,Fred>

ou

Code c++ : S�lectionner tout
std::map<std::string,Fred*>

ou encore un entier qui sera un indice dans un tableau du genre

Code c++ : S�lectionner tout
Fred* array = new Fred[maxNumFreds]

ou tout simplement un pointeur sur Fred, ou n'importe quoi d'autre.

Les d�butants pensent souvent en termes de pointeurs, mais en r�alit�, ils prennent un risque. Que se passe-t-il si l'objet Fred doit �tre d�plac� ? Comment savoir quand il est sans risque d'effacer l'objet Fred ? Que se passe-t-il si l'objet doit �tre s�rialis� ?
La plupart du temps, on aura tendance � ajouter de plus en plus de couches d'indirections pour g�rer ces cas de figure. Par exemple, le handle sur Fred devrait �tre un Fred **, o� le pointeur pointant sur Fred* est suppos� ne jamais �tre d�plac�, mais � un moment le pointeur doit �tre d�plac�, on met seulement � jour le pointeur sur Fred *. Ou vous d�cidez que le handle devient un entier d�signant l'objet Fred dans une table, etc.

Le fait est que nous utilisons le mot handle tant que nous ne savons pas le d�tail de ce que nous allons faire.

Une autre circonstance dans laquelle nous utilisons le mot handle est quand on pr�f�re rester vague au sujet de ce que nous avons d�j� fait (on utilise parfois le terme ��cookie�� pour cela, par ex. � Le programme passe un cookie qui est utilis� pour identifier de fa�on unique l'objet Fred ad�quat �). La raison pour laquelle nous voulons (parfois) rester vague est de minimiser les effets de bord si les d�tails d'impl�mentations devaient changer. Par exemple, si quelqu'un change le handle qui �tait une cha�ne qui servait � faire une recherche dans une liste de hachage en un entier qui sert � indicer une table, cela pourrait causer le changement de dizaines de milliers de lignes de code.

Pour faciliter la maintenance quand les d�tails de repr�sentation d'un handle changent (ou tout simplement pour rendre le code plus lisible), nous encapsulerons le handle dans une classe. Cette classe surchargera souvent les op�rateurs -> et * (comme le handle agit comme un pointeur, il semble logique qu'il ressemble � un pointeur).

Mis � jour le 10 f�vrier 2004 Cline

Proposer une nouvelle r�ponse sur la FAQ

Ce n'est pas l'endroit pour poser des questions, allez plut�t sur le forum de la rubrique pour �a


R�ponse � la question

Liens sous la question
pr�c�dent sommaire suivant
 

Les sources pr�sent�es sur cette page sont libres de droits et vous pouvez les utiliser � votre convenance. Par contre, la page de pr�sentation constitue une �uvre intellectuelle prot�g�e par les droits d'auteur. Copyright � 2025 Developpez Developpez LLC. Tous droits r�serv�s Developpez LLC. Aucune reproduction, m�me partielle, ne peut �tre faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'� trois ans de prison et jusqu'� 300 000 � de dommages et int�r�ts.