Différence entre les arguments de fonction déclarés avec & et * dans C ++

J’ai tapé l’exemple suivant:

#include  double f(double* x, double* y) { std::cout << "val x: " << *x << "\n"; std::cout << "val y: " << *y << "\n"; return *x * *y; } double f2(double &x, double &y) { std::cout << "val x: " << x << "\n"; std::cout << "val y: " << y << "\n"; return x * y; } int main() { double a, b; a = 2; b = 3; std::cout << f(&a, &b) << "\n"; std::cout << f2(a, b) << "\n"; return 0; } 

Dans la fonction f je déclare x et y comme des pointeurs dont je peux obtenir la valeur en utilisant *x . En appelant f j’ai besoin de passer l’adresse de mes arguments passés, c’est pourquoi je passe &a, &b . f2 est la même sauf que la définition est différente.

Maintenant, ma question est la suivante: sont-ils vraiment les mêmes en ce qui concerne la gestion de la mémoire? Les deux ne font pas de copie de la valeur passée mais transmettent plutôt une référence? Je me demande à propos de f2 car je ne pouvais pas lire l’adresse de x dans f2 alors j’en sais plus sur x et y dans f (là je connais l’adresse ET la valeur).

Merci d’avance!

Edit : Ok merci, après avoir fait quelques recherches, j’ai trouvé un sujet très utile:

Pointeur ou référence Il existe également un lien vers les lignes direcsortingces de Google pour le codage http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Reference_Arguments, ce qui est très useful goût) pour rendre plus clair

    f2 prend ses arguments par référence, ce qui est essentiellement un alias pour les arguments que vous passez. La différence entre le pointeur et la référence est qu’une référence ne peut pas être NULL. Avec le f vous devez passer l’ adresse (using & operator) des parameters que vous passez au pointeur, où lorsque vous passez par référence, vous passez simplement les parameters et l’alias est créé.

    Passer par la référence const ( const double& ref ) est préférable lorsque vous n’allez pas modifier les arguments à l’intérieur de la fonction, et lorsque vous allez les modifier, utilisez une référence non-const.

    Les pointeurs sont principalement utilisés lorsque vous devez être capable de passer NULL à vos parameters, de toute évidence, vous devrez vérifier dans votre fonction si le pointeur n’était pas NULL avant de l’utiliser.

    Ceci est juste du sucre syntaxique pour éviter d’avoir à utiliser * chaque fois que vous référencez l’argument. Vous pouvez toujours utiliser & pour avoir l’adresse de x dans f2 .

    Une autre différence qui n’a pas été mentionnée est que vous ne pouvez pas changer à quoi une référence fait référence. Cela ne fait pas beaucoup de différence dans l’exemple d’appel de fonction montré dans la question d’origine.

     int X(10), Y(20); int *pX = X; int& rY = Y; *pX = 15; // change value of X rY = 25; // change value of Y pX = Y; // pX now points to Y 

    rY pointe toujours vers Y et ne peut pas être déplacé.

    Les références ne peuvent pas être utilisées pour indexer des tableaux simples comme des pointeurs.

    Dans ma tête, les parameters des fonctions sont toujours passés par valeur. Passer un int est facile à imaginer, passer un double est juste plus grand et passer une struct ou une class peut être très important.
    Mais passer un pointeur à quelque chose, eh bien, vous ne faites que passer une adresse par valeur. (Un pointeur est souvent une taille commode pour le processeur comme un int .)
    Une référence est très similaire, et je pense certainement à une référence comme un pointeur, mais avec le sucre syntaxique pour le faire ressembler à l’object auquel il se réfère a été passé par valeur.

    Vous pouvez également penser à une référence en tant que pointeur const , c’est-à-dire:

     int i; int j; int* p = &i; // pointer to i int* const cp = p; // cp points to i, but cp cannot be modified p = &j; // OK - p is modified to point to j *cp = 0; // OK - i is overwritten cp = &j; // ERROR - cp cannot be modified int& ri = i; // ri refers to i ri = 1; // i is overwritten ri = j; // i is overwritten again // Did you think ri might refer to j? 

    Ainsi, un pointeur double le temps: c’est une valeur à part entière, mais il peut aussi pointer vers une autre valeur lorsque vous le déréférencer, par exemple: *p .
    De plus, avoir des parameters de référence signifie que vous ne pouvez pas les faire référence à autre chose pendant la durée de la fonction car il n’y a aucun moyen de l’exprimer.

    Une référence est supposée ne pas pouvoir être initialisée avec null , mais considérez ceci:

     void foo(int& i); int* p = 0; foo(*p); 

    Cela signifie que les pointeurs doivent être vérifiés avant de les utiliser, mais les références ne peuvent pas être vérifiées. L’implémentation de foo() pourrait essayer de lire ou d’écrire sur i ce qui provoquerait une violation d’access.

    Dans l’exemple ci-dessus, le pointeur p aurait dû être vérifié avant d’être utilisé dans l’appel à foo :

     if (p) foo(*p); 

    Vous devriez avoir été capable de lire l’adresse x dans les deux fonctions.

    Pour ce faire dans f2 , vous devez bien sûr préfixer x par un & puisque là, x est une référence à un double et vous voulez une adresse .

    Une différence notable entre les références et les pointeurs est que le premier ne peut pas être NULL. Vous devez transmettre quelque chose (valide) alors que lorsque vous fournissez un pointeur, vous devez spécifier dans la documentation si le passage à NULL est autorisé / bien défini.

    Une autre différence est une question de lisibilité: l’utilisation de références au lieu de pointeurs (si possible) rend le code moins encombré avec * et -> .