2010-09-01 4 views
1

Je pense que ce qui suit est vraiment basique mais je ne comprends pas vraiment ce que seraient les "avantages" d'un de ces codes.Question sur les références

Ayant ceci:

int main() 
{ 
    int a = 10; 
    f(a); 
    return 0; 
} 

Quelle serait la différence entre

void f(int& a) 
{ 
    int& b = a; 
} 

et

void f(int& a) 
{ 
    int b = a; 
} 

En particulier, dans le cas où f serait plutôt le constructeur d'un classe et où au lieu d'un int nous avons un gros objet.

J'irais avec la deuxième possibilité ... Que pensez-vous?

Merci.

Edit:

Tout d'abord, en regardant les réponses, je pensais que j'étais mort cérébrale quand je posté la question, mais en réalité j'ai trouvé intéressant (et sous-questions réponses!) Dans les commentaires.

Répondre

4

Première:

void f(int& a) { 
    int& b = a; 
} 

L'appelant passe dans un a, que nous obtenons comme une référence à a de l'appelant. Ensuite, nous créons une nouvelle référence b qui se réfère à a, qui est toujours le a de l'appelant. Par conséquent, toute modification apportée par l'appelant sera visible à f et à sa classe conteneur, et toute modification apportée à f à a ou à b aura une incidence sur ce que l'appelant a transmis comme a.

void f(int& a) { 
    int b = a; 
} 

Ici, b est une nouvelle variable, un int, qui prend copie de a. Les modifications apportées à b n'affecteront pas l'appelant, et l'appelant ne touchera pas b. Mais un moyen plus rapide d'écrire la même chose est:

void f(int b) { 
} 

et se passer du tout référence a.En particulier, cela montre dans le prototype que la fonction ne va pas modifier son paramètre, car elle ne le peut pas; tandis qu'un prototype de void f (int &a) indique que peut modifier a.

Edit: si vous avez besoin pour éviter toute copie, une troisième option (tm) est une référence à const:

void f(const int &a) { 
    const int &b = a; 
} 

intérieur f, ni a ni b peuvent être modifiés, de sorte qu'il ne peut pas affecter l'appelant, mais la copie est évitée en utilisant une référence à const. Il y a toujours un problème potentiel que tous les changements à a causés par l'appelant seront visibles à l'intérieur de l'objet, car il n'y a qu'un seul élément de données réel a et beaucoup de noms pour cela; C'est quelque chose que vous auriez à documenter pour s'assurer que l'appelant ne fait pas une telle chose.

+0

Merci! Donc pour construire une classe sans n'importe quelle copie je devrais avoir un membre qui est une référence, et le constructeur doit également accepter une référence en tant que paramètre? –

+1

Cedric: voir mon édition. –

+0

+1: Je préférerais le terme "référence à const" au lieu de "const reference" – Chubsdad

4

int& b = a ne copie pas un, int b = a fait. Plus important encore, l'appelant de votre constructeur peut changer l'objet et vous verrez ces changements dans votre nouvel objet. Pire encore: Si l'appelant détruit l'objet (ou qu'il est automatiquement détruit), votre objet a une référence invalide.

+0

Donc 'f (int a) {int & b=a;)' et 'f (int & a) {int b = a;}' seraient équivallents? En terme de copie. –

+0

@Cedric H .: Dans le premier cas 'int & b - a', une référence est en cours de création à une variable locale de la pile à savoir le paramètre formel 'a'. Il est très dangereux au cas où vous voulez retourner une référence à partir de la fonction – Chubsdad

2

La deuxième version crée une copie de la variable tandis que la première génère uniquement une autre référence à l'objet d'origine. Si vous avez juste une référence, de mauvaises choses (tm) se produiront si l'appelant détruit son objet. Donc, vous voulez probablement aller avec la deuxième version (sauf si vous pouvez être sûr que l'utilisation d'une référence est sûre).

+0

Mais si je dois éviter toute copie, je devrais faire 'f (int & a) {int & b =a;}' ou 'f (int * a) {int * b = a;} '(et appelez f (& a)' dans le second cas)? –