Passer des entiers en tant que références constantes par rapport à la copie

Cela pourrait être une question stupide, mais je remarque que dans un bon nombre d’API, beaucoup de signatures de méthodes qui prennent des parameters entiers qui ne sont pas destinés à être modifiés ressemblent à ceci:

void method(int x);

plutôt que:

void method(const int &x);

Pour moi, il semble que les deux fonctionneraient exactement de la même manière. (EDIT: apparemment pas dans certains cas, voir la réponse de R Samuel Klatchko) Dans le premier cas, la valeur est copiée et ne peut donc pas changer l’original. Dans ce dernier cas, une référence constante est transmise, de sorte que l’original ne peut pas être modifié.

Qu’est-ce que je veux savoir, c’est pourquoi l’un sur l’autre – est-ce parce que la performance est fondamentalement la même ou même meilleure avec la première? en passant par exemple une valeur de 16 bits ou une valeur de 32 bits plutôt qu’une adresse 32 bits ou 64 bits? C’était la seule raison logique à laquelle je pouvais penser, je veux juste savoir si c’est correct, et si non, pourquoi et quand vous préféreriez int x sur const int &x et / ou vice versa. Merci.

Ce n’est pas seulement le coût du passage d’un pointeur (c’est essentiellement une référence), mais aussi le dé-référencement dans le corps de la méthode appelée pour récupérer la valeur sous-jacente.

C’est pourquoi le passage d’un int par value sera pratiquement garanti (De plus, le compilateur peut optimiser et simplement passer l’ int via des registres de processeurs, éliminant ainsi le besoin de le pousser sur la stack).

Pour moi, il semble que les deux fonctionneraient exactement de la même manière.

Cela dépend exactement de la référence. Voici un exemple certes composé qui changerait selon que vous passiez une référence ou une valeur:

 static int global_value = 0; int doit(int x) { ++global_value; return x + 1; } int main() { return doit(global_value); } 

Ce code se comportera différemment selon que vous ayez int doit(int) ou int doit(const int &)

Les entiers ont généralement la taille du mot natif du processeur et peuvent facilement passer dans un registre. De ce sharepoint vue, il n’y a pas de différence entre le passage par valeur ou le passage par référence constante.

En cas de doute, imprimez la liste des langages d’assemblage pour vos fonctions afin de savoir comment le compilateur transmet l’argument. Imprimer pour les deux passes par valeur et passer par référence constante.

En outre, lors du passage par valeur, la fonction peut modifier la copie. Lors du passage par référence constante, la fonction ne peut pas modifier la variable (marquée comme const).

  • Selon le jeu d’instructions sous-jacent, un paramètre entier peut être transmis comme registre ou sur la stack. L’enregistrement est nettement plus rapide que l’access à la mémoire, ce qui serait toujours nécessaire dans le cas des const const (en tenant compte des architectures antécédents de cache)

  • Vous ne pouvez pas passer un littéral int en tant que const int &

  • Les casts de type explicites vous permettent de convertir un const int & en * (const int *) en ouvrant la possibilité de changer la valeur de la référence transmise

Il y aura probablement une très petite désoptimisation pour le passage par référence, car au moins une référence devra avoir lieu pour obtenir la valeur réelle (à moins que l’appel ne soit incorporé, le compilateur ne peut pas simplement transmettre la valeur due à En fait, le site et la fonction d’appel peuvent être compilés séparément, et il est valide et bien défini pour rejeter le const pour un paramètre passé qui n’est pas lui-même const – voir Quels sont les avantages de passer des types intégraux par const ref ). Notez toutefois que la «désoptimisation» est susceptible d’être si faible qu’elle est difficile à mesurer.

La plupart des gens semblent ne pas aimer les contrôles intégrés pour les modules intégrés (certains en ont beaucoup). Cependant, je pense que cela peut être préférable dans certains cas si vous voulez que le compilateur vous aide à vous assurer que la valeur n’est pas modifiée accidentellement dans la fonction. Ce n’est pas une grande chose, mais parfois cela peut aider.