49 votes

Est-il préférable de supprimer "const" devant les types "primitifs" utilisés comme paramètres de fonction dans l'en-tête?

Dans le processus de révision du code, un de mes collègues m'a indiqué que "const"s en face de "type primitif" qui est utilisé comme paramètre d'une fonction dans un en-tête est vide de sens, et il a recommandé de supprimer ces "const"s. Il a suggéré à l'aide de "const" uniquement dans le fichier source dans de tels cas. Les types primitifs moyenne de types tels que "int", "char", "float", etc.

Le suivant est un exemple.

exemple.h

int ProcessScore(const int score);

example.cc

int ProcessScore(const int score) {
  // Do some calculation using score
  return some_value;
}

Sa suggestion est de faire comme suit:

exemple.h

int ProcessScore(int score);  // const is removed here.

example.cc

int ProcessScore(const int score) {
  // Do some calculation using score
  return some_value;
}

Mais je suis un peu confus. Généralement, l'utilisateur de regarder uniquement l'en-tête, donc si il y a incohérence entre la tête et le fichier source, il peut causer de la confusion.

Quelqu'un pourrait-il donner quelques conseils à ce sujet?

71voto

StoryTeller Points 6139

Pour tous les types (et pas seulement primitives), le haut niveau const qualificatifs dans la déclaration de fonction sont ignorés. Donc la suite de quatre déclarer toutes la même fonction:

void foo(int const i, int const j);
void foo(int i, int const j);
void foo(int const i, int j);
void foo(int i, int j);

Le qualificateur const n'est pas ignorée à l'intérieur de la fonction du corps, cependant. De là, il peut avoir un impact sur const exactitude. Mais c'est un détail de l'implémentation de la fonction. De sorte que le consensus général est ceci:

  1. Quitter la const de la déclaration. C'est juste le désordre, et n'affecte pas la façon dont les clients pourront faire appel à la fonction.

  2. Quitter la const dans la définition si vous souhaitez que le compilateur de capture accidentelle, la modification du paramètre.

41voto

Artemy Vysotsky Points 1999

Les paramètres de la fonction déclarée const et sans const est la même en venant à la résolution de surcharge. Ainsi, par exemple, les fonctions de

void f(int);
void f(const int);

sont les mêmes et ne peuvent être définis ensemble. En conséquence, il est préférable de ne pas utiliser const dans la déclaration pour les paramètres à tout pour éviter les doubles emplois. (Je ne parle pas de const référence ou pointeur const - depuis le modificateur const n'est pas au top niveau.)

Voici la citation exacte de la norme.

Après la production de la liste de types de paramètres, tout en haut au niveau de cv-qualificatifs, la modification d'un paramètre de type sont supprimés lors de la formation du type de fonction. La liste de transformer les types de paramètre et de la présence ou de l'absence de points de suspension ou un paramètre de la fonction pack est la fonction du paramètre de type de liste. [ Note: Cette transformation ne une incidence sur les types des paramètres. Par exemple, int(*)(const int p, decltype(p)*) et int(*)(int, const int*) sont identiques types. - la note de fin ]

L'utilité de const dans la définition de la fonction est discutable, le raisonnement derrière est le même que l'aide const pour la déclaration d'une variable locale - il démontre à d'autres programmeurs de la lecture du code de la cette valeur ne sera pas modifiée à l'intérieur de la fonction.

15voto

Dúthomhas Points 1163

Suivre les recommandations qui vous est donnée dans la revue de code.

À l'aide de const de la valeur des arguments n'a pas de valeur sémantique - il n'est significatif (potentiellement) pour la mise en œuvre de votre fonction - et même dans ce cas, je dirais que c'est inutile.

edit: Juste pour être clair: votre prototype de la fonction est l' interface publique de votre fonction. Ce const n'est de vous offrir une garantie que vous ne serez pas modifier les références.

int a = 7;
do_something( a );

void do_something(       int& x );  // 'a' may be modified
void do_something( const int& x );  // I will not modify 'a'
void do_something(       int  x );  // no one cares what happens to x

À l'aide de const est quelque chose qui s'apparente à de TMI - c'est sans importance, n'importe où, sauf à l'intérieur de la fonction de si oui ou non 'x' est modifié.

edit2: j'aime également beaucoup d'informations dans du Conteur répondre

7voto

Bitwize Points 555

Comme beaucoup d'autres personnes ont répondu, à partir d'un point de vue API, les suivantes sont toutes équivalentes, et sont les mêmes pour les surcharge-résolution:

void foo( int );
void foo( const int );

Mais une meilleure question est de savoir si ou non de cette offre aucun sens sémantique à un consommateur de cette API, ou si elle prévoit l'application de la loi de bons comportements à partir d'un développeur de l'application.

Sans bien défini développeur de codage des lignes directrices qui définissent expressément cette, const scalaire arguments n'ont pas facilement évident de sens sémantique.

À partir d'un consommateur: const int ne change pas votre entrée. Il peut encore être un littéral, ou il peut être à partir d'une autre variable (les deux const ou de non-const)

À partir d'un développeur: const int impose une restriction sur une copie locale d'une variable (dans ce cas, un argument de fonction). Cela signifie simplement modifier l'argument, vous prenez une autre copie de la variable et de le modifier à la place.

Lorsque vous appelez une fonction qui accepte un argument par valeur, une copie de cet argument sur la pile de la fonction appelée. Cela donne à la fonction de copie locale de l'argument pour l'ensemble de son champ d'application, qui peuvent ensuite être modifiés, utilisés pour les calculs, etc -- sans affecter l'entrée d'origine est passé dans l'appel. Effectivement, cela fournit une variable locale argument de son entrée.

En marquant l'argument de la" const, cela signifie simplement que cette copie ne peut pas être modifié, mais ce n'est pas d'interdire le développeur de le copier et de faire des modifications à cette copie. Étant donné que c'était une copie depuis le début, il ne fait pas valoir tout ce que beaucoup de l'intérieur de la mise en œuvre et au final ne fait pas beaucoup de différence du point de vue du consommateur.

Ceci est en contraste avec le passage par référence, dans lequel un renvoi à l' int& est sémantiquement différent de const int&. Le premier est capable de muter son entrée; ce dernier est seulement capable d'observer l'entrée (à condition que la mise en œuvre n'a pas d' const_cast le const-ness loin -, mais permet d'ignorer cette possibilité); ainsi, const-ness sur des références implicites, de sens sémantique.

Il ne fournit pas beaucoup d'avantage dans l'API publique; et (omi) introduit des restrictions inutiles à la mise en œuvre. Comme un arbitraire, exemple artificiel -- une fonction simple comme:

void do_n_times( int n )
{
   while( n-- > 0 ) {
       // do something n times
   } 
}

devrait maintenant être écrite à l'aide d'une copie superflue:

void do_n_times( const int n )
{
    auto n_copy = n;
    while( n_copy-- > 0 ) {
        // do something n times
    }
}

Indépendamment de si const scalaires sont utilisés dans l'API publique, une clé, c'est d'être cohérent avec la conception. Si l'API au hasard des commutateurs entre l'utilisation d' const scalaire arguments à l'aide de non-const scalaires, alors il peut causer de la confusion quant à savoir s'il est destiné à être implicite du sens à la consommation.

TL;DR: const types scalaires dans une API publique de ne pas transmettre de sens sémantique sauf s'il est explicitement défini par vos propres lignes directrices relatives à votre domaine.

-2voto

Lio Points 17

J'ai pensé qu' const est une indication pour le compilateur que certaines expressions ne pas changer et de les optimiser en conséquence. Pour exemple, j'ai été tester si un nombre est premier par la recherche de diviseurs jusqu'à la racine carrée du nombre et j'ai pensé que la déclaration de l'argument const serait de prendre l' sqrt(n) à l'extérieur de l' for boucle, mais il n'a pas.

Il peut ne pas être nécessaire dans l'en-tête, mais là encore, on pourrait dire que tous vous avez besoin est de ne pas modifier l'argument et il n'est jamais nécessaire. Je préfère le voir const où il est const, et pas seulement dans la source, mais dans l'en-tête trop. Les incohérences entre la déclaration et la définition de me faire circonspect. Juste mon avis.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X