Pointeurs et références en C + + Partie 2

2 mai 2009 · Posted in C / C + +

Poursuivant cet effort de série de messages concernant les pointeurs et les références, qui commença à parler de pointeurs, références discuter aujourd'hui.

Une référence est un alias pour un objet, un alias. D'ailleurs, qui dit que ce n'est pas moi, mais tout le Bjarne Stroustrup, autour du thème 5.5 de son livre, dont le contenu est si bon que je remarque seulement maintenant que la couverture a une vague déferlante en forme de C. I like that cover!

Déclarant Références

Une référence à un type particulier est déclaré en ajoutant le caractère & (et commercial ou esperluette) après le nom du type de référence. Notez que la même façon que la déclaration des pointeurs, nous traitons le caractère & comme une agence et non un opérateur. Il ya une déclaration de l'opérateur de pointeurs ou des références. C'est juste une notation de la langue. Étant donné un type T, l'expression signifie que T & T référence. Par exemple:

  / / Déclare une variable entière d'origine.
 / / Elle pourrait également être char, float, etc.
 int i;

 / / Declare références à la variable i.
 / / Tous les formulaires sont équivalents, mais je préfère la première.
 / / Notez que les types de références doivent être les mêmes
 / / Les variables référencées.
 ra = i ; int & ra = i;
 rb = i ; int & rb = i;
 rc = i ; int & rc = i;

 / / Contrairement aux pointeurs, la ligne suivante génère un
 / / Erreur de compilation.  Vous pourriez dire pourquoi?
 r1, & r2 ; int & r1, & r2; 

Alors qu'en C + + références rappeler quelques conseils, ils sont assez différents. Contrairement à ce qui se passe avec des pointeurs, une référence doit être initialisée dans sa déclaration. Essayer de déclarer une référence sans l'initialiser génère une erreur à la compilation, à savoir, le compilateur crache au visage "playboy perdu, perdu!". La seule exception à cette règle est pour référence déclarés comme extern, car ils seront initialisés à un autre point du programme, mais c'est une autre rant.

Si vous tentez de tricher en déclarant une référence extern sans l'initialiser le compilateur va pas se plaindre. Si elle n'est jamais utilisée, ok. Si le compilateur est intelligent et a noté qu'il n'est pas utilisé, vous pouvez même le supprimer de la liste des symboles. Mais s'il est utilisé dans n'importe quelle partie du programme, l'éditeur de liens va se moquer de votre visage riant "undefined reference to 'nome_da_variavel». Donc, faire les choses bien. A déclaré une référence? Ainsi, il iniclalize. extern? Êtes-vous sûr de savoir ce que vous faites?

La logique derrière cela est que la référence était destiné à être un nom pour quelque chose. Si vous n'avez pas de boot, il ne nommerai pas pour rien, alors il est logique. Un détail très important est d'initialiser une référence n'est pas d'attribuer une valeur à elle. Comme prório Bjarne dit, aucun opérateur exploite des modalités, à savoir, il n'existe aucun moyen d'allouer, à additionner, soustraire, etc, avec une référence. À titre de référence est un alias pour un objet, chaque opérateur agit NESE objet, pas la référence. Une fois initialisé, une référence toujours référence au même objet.

Le premier piège de références, ainsi que des pointeurs est la question de la taille. Bien que la taille d'un pointeur (et autres structures de données) peuvent être obtenus auprès de l'opérateur sizeof, la taille d'un renvoi ne peut être obtenue par des techniques conventionnelles, car lors de l'application de l'opérateur sizeof sur une référence, nous sommes effectivement appliquant l'objet exploitant pour lequel il des références, comme nous l'avons vu dans le paragraphe précédent.

  17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
  char c;
 int i;
 double d;

   rc = c ; char & rc = c;
    ri = i ; int & ri = i;
 rd = d ; Double & e = d;

 / / L'opérateur sizeof dit la taille du type de son argument.
 "Size of char:    " << sizeof ( c ) << " bytes" << endl ; cout << "Taille du char:" <<sizeof (c) << "octets" <<endl;
 "Size of int:     " << sizeof ( i ) << " bytes" << endl ; cout << "Size of int:" <<sizeof (i) << "octets" <<endl;
 "Size of double:  " << sizeof ( d ) << " bytes" << endl ; cout << "Taille du double:" <<sizeof (d) << "octets" <<endl;

 endl ; cout <<endl;

 "Size of char&:   " << sizeof ( rc ) << " bytes" << endl ; cout << "Taille du char &:" <<sizeof (rc) << "octets" <<endl;
 "Size of int&:    " << sizeof ( ri ) << " bytes" << endl ; cout << "Taille de l'int &:" <<sizeof (ri) << "octets" <<endl;
 "Size of double&: " << sizeof ( rd ) << " bytes" << endl ; cout << "Taille du double &:" <<sizeof (rd) << "octets" <<endl; 

Techniques pour la taille des références sont au-delà du champ d'application de ce texte, mais je tiens à en parler à l'avenir. Pour l'instant, je vais juste dire non à montrer que, le cas échéant, la taille d'une référence est identique à la taille d'un pointeur.

La bonne partie de l'histoire est que, souvent, la taille des pointeurs et les références sont beaucoup moins pertinentes que les dimensions des objets référencés ou pointu. Je n'ai personnellement jamais eu à utiliser cette information, mais pour le développement ou sur différentes architectures pour des systèmes embarqués, il est devenu plus intéressant.

Utilisation des références

L'utilisation de références est maintenant beaucoup plus simple que les pointeurs, parce que les opérateurs ne sont pas nécessaires pour extraire des adresses ou de référencement. Références variables sont utilisées comme des variables communes, indiquant qu'une opération effectuée dans une référence toujours une incidence sur l'objet référencé.

  17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
  int x, y;
 rx = x ; int & rx = x;
 ry = y ; int & ry = y;

 ; x = 13;
 ; y = 10;

 ; // A atribuição é automaticamente aplicada em x. Rx = 42 / / Le prix est automatiquement appliquée à x.
 // O incremento é automaticamente aplicado em y. ry + + / / L'incrément est appliqué automatiquement à y.

 "x:  " << x << endl ; // Valor de x. cout << "x:" <<x <<endl; / / valeur de x.
 "y:  " << y << endl ; // Valor de y. cout << "y:" <<y <<endl; / / valeur de y.
 "rx: " << rx << endl ; // Valor de rx == x. cout << "Rx:" <<<Rx <endl; / / value == x. rx
 "ry: " << ry << endl ; // Valor de ry == y. cout << "re:" <<ry <<endl; / / ry value == y. 

En utilisant une référence soit la plus transparente pour le programmeur, il n'avait pas besoin de savoir que c'est une référence. Il suffit de l'utiliser comme une variable ordinaire. Avec mon imagination limitée ne vois pas comment quelqu'un peut être excommunié pour utilisation de clauses de façon inappropriée. Bien que certains ont toujours l'esprit de porc qui peut faire chier avec des références, est beaucoup plus facile d'obtenir déclenché par Saci à manipuler des pointeurs.

Adresses et références

Du point de vue de Murphy, les références sont laid, ennuyeux et stupide, parce qu'il ya peu de danger pour le faire avec eux. Même que l'adresse il ya beaucoup de surprises (le fera?). Considérons le code ci-dessous:

  17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
  10 ; int a = 10;
 13 ; int b = 13;

 ra = a ; int & ra = a;
 rb = b ; int & rb = b;

 ; RA = 42;
 ; rb = 7;

 "ra  = " << ra << endl ; // O valor de ra == 42. cout << "ra =" <<<Ra <endl; / / La valeur de ra == 42.
 "rb  = " << rb << endl ; // O valor de rb == 7. cout << "r =" <<<rb <endl; / / La valeur de RB == 7.
 "a   = " << a << endl ; // O valor de a == ra == 42. cout << "a =" <<a <<endl; / / La valeur de la RA == == 42.
 "b   = " << b << endl ; // O valor de b == rb == 7. cout << "b =" <<b <<endl; / / La valeur de RB b == == 7.

 "&a  = " << & a << endl ; // O endereço de a. cout << "& a =" <<& a <<endl; / / L'adresse de a.
 "&b  = " << & b << endl ; // O endereço de b. cout << "& b =" <<& b <<endl; / / L'adresse de b.
 "&ra = " << & ra << endl ; // O endereço de ra == &a. cout << "& ra =" <<n <<endl; / / L'adresse de ra == & A.
 "&rb = " << & rb << endl ; // O endereço de rb == &b. cout << "& rb =" <<rb <<endl; / / L'adresse de RB == & B. 

Dans les lignes 17 et 18, je déclare deux variables entières (aurions pu le faire avec un exemple ...). Dans les lignes 20 et 21, je déclare deux références, le référencement des deux variables précédentes. Par la suite, la RA et RB variables ne sont que des alias pour les variables a et b. Comme mentionné ci-dessus, tout opérateur appliqué aux références opère de manière effective sur les objets référencés, afin que chaque paire de variable de référence a toujours la même valeur.

Ce qui est intéressant à noter est que les adresses des références sont exactement les mêmes adresses des variables font référence, à la différence des pointeurs qui avaient leurs propres adresses. Pourquoi? Parce que tu es tombé Pegadinha do Malandro. N'oubliez pas que parler de tout opérateur de s'appliquer à une référence? Eh bien, ici utilisé l'opérateur & est l'adresse "", qui est aussi appliqué directement sur les variables d'origine et non dans les références. Les mêmes techniques ninja utilisé pour obtenir la taille des références sont nécessaires pour obtenir les adresses d'entre eux.

Encore une fois, la partie amusante est que le mécanisme de référence est conçu pour être aussi transparents que possible pour le programmeur. Tailles et l'adresse physique de références sont des informations non pertinentes du point de vue de la «normale» programmer en C + +.

Les différences et les similitudes entre les pointeurs et les références

Les deux pointeurs et les références sont les mécanismes d'indirection en C + +, ou des mécanismes sont utilisés à partir d'un symbole (variable) je serai en mesure de manipuler un autre objet.

Les principaux usages pour les pointeurs sont généralement liées à la gestion et la manipulation de la mémoire dynamique, la création et la destruction des objets et de formes pour des occasions spéciales, ainsi que «le passage de paramètres par référence» (à ce qu'il cite). Étant donné que les références sont plus habitués à passer par référence (pourquoi est-il?) Et la surcharge de l'opérateur.

Au fond, tout ce que nous pouvons faire avec les références ne peuvent être imitées avec des pointeurs. De l'autre, réciproquement à ne pas toujours vrai. Le grand avantage d'entre eux, cependant, est que l'indirection devenir complètement transparent pour le programmeur.

Une allégorie intéressante pour aider à mieux comprendre les différences entre les pointeurs et les références est le surnom. Par exemple: Imaginons qu'une personne, disons, Dunga, est notre variable d'origine, l'objet. Dunga est déjà une référence à Dunga, il est un alias pour le même objet sont la même personne. Déjà mère de Dunga (ou Dunga, peu importe), qui est cité par les fans de main ferme, peut être considéré comme un pointeur vers elle, parce que certains fournisseurs de données de vocabulaire, a fait un compliment à lui, la vérité est indirectement ciblées lui.

Liens

Commentaires

5 réponses à "Pointeurs et références en C + + Partie 2"

  1. Wanderley Caloni le Mai 2, 2009 10:58

    Great article!

    Malheureusement, les références ne sont pas aussi inoffensifs en ce qu'ils semblent être. Imaginez les situations suivantes:

    1. Quelqu'un renvoie une référence à une variable locale non-statique:

      string & QueroEconomizarCopiasDeString ()
     (
        string ret;
        / / Hack hack hack
        // espertão... return ret; / / malin ...
     ) 

    Dans ce cas, la portée se termine avant même que quelqu'un se sert de la référence.

    La solution est d'obtenir une référence comme un paramètre et faire une seule copie: pour la variable «out».

    2. Quelqu'un veut utiliser la mémoire dynamique en tant que variables ordinaires:

      int main ()
     (
        pi = new int ; int * pi = new int;
    
        / / Lignes de code pour oublier qui est pi
    
        ri = * pi ; // acho ponteiros complicado int & ri = pi * / / I pointeurs compliquée
    
        / / Plus de lignes de code d'oublier ri et PI
    
        delete pi;
    
        / Tcharammm ...
    
        ; // é a resposta para tudo, não? RI = 42, / / est la réponse à tout, non?
     ) 

    Ces exemples semblent bête, mais pas aussi improbable qu'il n'y paraît. Juste le code à être désinfectés avec les design patterns ou de tout autre non-sens et il explose sans que vous sachiez ce qui s'est passé.

    [] S

  2. blab le Mai 2, 2009 12:07

    Caloni, tu es un gars trop hâtive :)

    Oui, vous avez absolument raison. Mais j'ai laissé faire exprès.
    Moi aussi, j'ai pas encore parlé à const pointeurs ou de références, ou même que l'association entre les pointeurs et les tableaux, mais je vais parler.

    Merci pour le compliment, il est très motivant.

    Abração

  3. Wanderley Caloni le Mai 2, 2009 20:08

    Ma naïveté, je pensais que j'avais donné qu'il se ferme lorsque vous avez dit «Du point de vue de Murphy, dont les références sont laides, ennuyeux et stupide, parce qu'il ya peu de danger potentiel pour le faire avec eux». En tout état de façon déjà recommandé votre article à un débutant, car il est réellement très bien expliqué pour ceux qui s'aventurent pour les différences entre C et C + +.

    J'attends la procédure.

    [] S

  4. Jorge Pereira le 5 Mai, 2009 02:36

    Partenaire jaser!

    Félicitations pour l'article, très bien!

    [] S

  5. [...] [...] Pointeiros et références

Laissez une réponse




Powered by WP Hashcash