web-dev-qa-db-fra.com

Différence entre la référence const et le paramètre normal

void DoWork(int n);
void DoWork(const int &n);

Quelle est la différence?

45
Pirate for Profit

La différence est plus importante lorsque vous passez une grande structure/classe.

struct MyData {
    int a,b,c,d,e,f,g,h;
    long array[1234];
};
void DoWork(MyData md);
void DoWork(const MyData& md);

lorsque vous utilisez le paramètre "normal", vous passez le paramètre par valeur et créez ainsi une copie du paramètre que vous passez. si vous utilisez la référence const, vous la transmettez par référence et les données d'origine ne sont pas copiées.

dans les deux cas, les données d'origine ne peuvent pas être modifiées depuis l'intérieur de la fonction.

MODIFIER:
Dans certains cas, les données originales peuvent être modifiées comme indiqué par Charles Bailey dans son réponse .

54
Afriza N. Arief

La différence importante est qu'en passant par la référence const, aucun nouvel objet n'est créé. Dans le corps de la fonction, le paramètre est en fait un alias pour l'objet transmis.

La référence étant une référence const, le corps de la fonction ne peut pas modifier directement la valeur de cet objet. Cela a une propriété similaire au passage par valeur où le corps de la fonction ne peut pas non plus modifier la valeur de l'objet qui a été transmis, dans ce cas, car le paramètre est une copie.

Il existe des différences cruciales. Si le paramètre est une référence const, mais que l'objet est passé, il ne s'agissait pas en fait de const, alors la valeur de l'objet peut être modifiée lors de l'appel de fonction lui-même.

Par exemple.

int a;

void DoWork(const int &n)
{
    a = n * 2;  // If n was a reference to a, n will have been doubled 

    f();  // Might change the value of whatever n refers to 
}

int main()
{
    DoWork(a);
}

De plus, si l'objet transmis n'était pas réellement const, la fonction pourrait (même si cela n'est pas conseillé) changer sa valeur avec un transtypage.

par exemple.

void DoWork(const int &n)
{
    const_cast<int&>(n) = 22;
}

Cela provoquerait un comportement indéfini si l'objet transmis était en fait const.

Lorsque le paramètre est transmis par référence const, les coûts supplémentaires incluent le déréférencement, la pire localité d'objet, moins de possibilités d'optimisation de la compilation.

Lorsque le paramètre est transmis par valeur et un coût supplémentaire est la nécessité de créer une copie de paramètre. En règle générale, cela n'est préoccupant que lorsque le type d'objet est grand.

53
CB Bailey

Il existe trois méthodes pour transmettre des valeurs dans la fonction

  1. Passer par valeur

    void f(int n){
        n = n + 10;
    }
    
    int main(){
        int x = 3;
        f(x);
        cout << x << endl;
    }
    

    Sortie: 3. Inconvénient: lorsque le paramètre x passe par la fonction f, le compilateur crée une copie en mémoire dans x. Donc gaspillage de mémoire.

  2. Passer par référence

    void f(int& n){
        n = n + 10;
    }
    
    int main(){
        int x = 3;
        f(x);
        cout << x << endl;
    }
    

    Sortie: 13. Il élimine le désavantage de passage par valeur, mais si le programmeur ne veut pas changer la valeur, utilisez une référence constante

  3. Référence constante

    void f(const int& n){
        n = n + 10; // Error: assignment of read-only reference  ‘n’
    }
    
    int main(){
        int x = 3;
        f(x);
        cout << x << endl;
    }
    

    Sortie: erreur de projection sur n = n + 10 car lorsque nous transmettons l'argument du paramètre de référence const, il s'agit d'un paramètre en lecture seule, vous ne pouvez pas modifier la valeur de n.

12
sneha

Avec

 void DoWork(int n);

n est une copie de la valeur du paramètre réel, et il est légal de changer la valeur de n dans la fonction. Avec

void DoWork(const int &n);

n est une référence au paramètre réel et il n'est pas légal de changer sa valeur.

6
Avi

Étant donné qu'aucun de vous n'a mentionné le mot-clé const ...

Le mot clé const modifie le type d'une déclaration de type ou le type d'un paramètre de fonction, empêchant la valeur de varier. (Source: MS)

En d'autres termes: le passage d'un paramètre par référence l'expose à la modification par l'appelé. L'utilisation du mot clé const empêche la modification.

2
Aoi Karasu

Tout d'abord, il n'y a pas de concept de références qualifiées cv. Ainsi, la terminologie "référence const" n'est pas correcte et est généralement utilisée pour décrire "référence à const". Il vaut mieux commencer à parler de ce que l'on veut dire.

$ 8.3.2/1- "Les références qualifiées Cv sont mal formées sauf lorsque les qualificatifs cv sont introduits à l'aide d'un typedef (7.1.3) ou d'un argument de type de modèle (14.3), auquel cas le cv- les qualificatifs sont ignorés. "

Voici les différences

$ 13.1 - "Seuls les spécificateurs de type const et volatile au niveau le plus à l'extérieur de la spécification de type de paramètre sont ignorés de cette manière; les spécificateurs de type const et volatile enfouis dans une spécification de type de paramètre sont significatifs et peuvent être utilisés pour distinguer les déclarations de fonctions surchargées. En particulier, pour tout type T, "pointeur vers T", "pointeur vers const T" et "pointeur vers T volatile" sont considérés comme des types de paramètres distincts, tout comme "référence vers T", "référence vers const T". "Et" référence au T. volatil "

void f(int &n){
   cout << 1; 
   n++;
}

void f(int const &n){
   cout << 2;
   //n++; // Error!, Non modifiable lvalue
}

int main(){
   int x = 2;

   f(x);        // Calls overload 1, after the call x is 3
   f(2);        // Calls overload 2
   f(2.2);      // Calls overload 2, a temporary of double is created $8.5/3
}
0
Chubsdad

La première méthode passe n par valeur, c'est-à-dire qu'une copie de n est envoyée à la fonction. Le second passe n par référence, ce qui signifie essentiellement qu'un pointeur vers le n avec lequel la fonction est appelée est envoyé à la fonction.

Pour les types intégraux comme int, cela n'a pas beaucoup de sens de passer comme référence const car la taille de la référence est généralement la même que la taille de la référence (le pointeur). Dans les cas où faire une copie coûte cher, il est généralement préférable de passer par référence const.

0
Andreas Brinck