En C / C ++, dois-je utiliser "const" dans les paramètres et les variables locales lorsque cela est possible?


13

Cette question est inspirée d' une question sur finalen java .

En C / C ++, dois-je utiliser constautant que possible?

Je sais qu'il y a déjà une question connexe concernant l'utilisation des constparamètres . Malheureusement, cette question et ses réponses ne répondent pas entièrement à ma question, car il s'agit uniquement de paramètres de fonction, mais j'aimerais également connaître d'autres cas (par exemple: les variables locales).

En outre, presque toutes les réponses à cette question disent que nous devrions utiliser constcar il contient des informations utiles sur l'accessibilité des variables. Mais cela semble entrer en conflit avec une réponse sur l'utilisation de final en Java, qui finalpeut être superflu s'il ne contient pas d'informations supplémentaires et il doit donc être omis pour garder le code court et propre.

Alors, dois-je utiliser constautant que possible? Si oui, pourquoi les conseils consten C ++ sont-ils différents de ceux finalen Java?

Réponses:


18

Tout d'abord, puisque vous avez fait référence à Java final, c'est une bête totalement différente de celle de const. Final signifie que la référence ne peut pas changer, mais ne dit rien sur la mutabilité. Const va plus loin en disant "une référence const ne peut pas muter", ce qui est une garantie beaucoup plus forte. Pour ce faire en Java, l'état interne doit être définitif et déterminé au moment de la construction. Const est beaucoup plus facile à utiliser et un objet existant peut être "promu" en référence const.

Oui, vous devez utiliser const autant que possible. Cela fait un contrat que votre code ne changera rien. N'oubliez pas qu'une variable non const peut être transmise à une fonction qui accepte un paramètre const. Vous pouvez toujours ajouter const, mais pas le supprimer (pas sans cast const qui est une très mauvaise idée).

La constance peut parfois être fastidieuse, mais elle contribue à garantir l'immuabilité. Ceci est crucial dans le code multi-thread où les threads partagent des objets. Il rend certaines tâches plus efficaces: au lieu de copier l'état, il suffit de réutiliser le même objet immuable. Les bibliothèques peuvent accepter des paramètres const afin de garantir au programmeur que non, votre objet ne changera pas de manière imprévisible dans le trou noir qu'est le ventre de la bibliothèque.


1
Votez parce que vous expliquez cela finalet constn'avez pas les mêmes garanties.
Bill Door

2
La constance est une question d'écriture, pas de mutabilité.
Basilevs

@Basilevs que se passe-t-il si vous écrivez sur un objet? Ça mute. Comment muter un objet? Écrivez-lui.

4
Que se passe-t-il si vous écrivez dans une référence const? Une erreur de compilation. Que se passe-t-il si vous écrivez à l'objet référencé quelque part par une référence const via une autre référence non const? Ça mute. Un objet immuable ne peut pas muter, donc const refernce ne fait pas nécessairement référence à un objet immuable.
Basilevs

@Basilevs votre observation ne s'applique qu'aux références const. Si un objet lui-même est déclaré const (pas seulement la référence), alors il est plus ou moins immuable (à moins que quelqu'un ne rejette néfaste la constness).
Matthew James Briggs

4

Personnellement, cela constme prend très peu de temps pour écrire et très peu de temps pour lire, généralement beaucoup moins que pour vérifier si un code mute la variable, et cela m'empêche en fait d'écrire des bogues (quelqu'un a-t-il jamais incrémenté son itérateur final par accident? Etc)

Je trouve également que le fait d'être strict sur l'utilisation de const me guide vers un meilleur code par d'autres moyens, comme la création de fonctions d'aide pour effectuer une initialisation non triviale.


4

Je vais être en désaccord avec les autres affiches et vous recommander de ne pas utiliser de niveau supérieur constsur les variables et paramètres locaux. (Les références et les pointeurs vers const, c.-à-d const T&. Sont différents, et vous devez les utiliser à des fins de correction à tout moment lorsque cela est approprié.)

Les avantages du niveau supérieur constsont:

  • Indique clairement que les variables locales ne sont pas destinées à être mutées.
  • Donne une erreur de compilation si vous tentez accidentellement de les muter.

Les inconvénients sont:

  • Désordre visuel.
  • Ne peut pas être utilisé sur des variables "pseudo-const", c'est-à-dire des variables qui sont initialisées d'une manière plus compliquée que la construction directe, mais non modifiées après, par exemple en utilisant getline:

    std::string line; // cannot be const
    std::getline(std::cin, line);
    // line should be const from here on out
  • Empêche l'optimisation du déplacement lors de l'appel et du retour de fonction:

    std::string f1();
    std::string f2(std::string s);
    std::string f3() {
      const std::string s = f1(); // s is not meant to be modified
      // but I still want the move optimization here:
      const std::string result = f2(std::move(s)); // this doesn't move
      // and I want the compiler to move out here:
      return result; // this will probably RVO, but if not, the move
                     // constructor will not be used due to the const
    }

J'ai travaillé sur une base de code où le local constétait beaucoup utilisé, et je l'ai trouvé pas du tout utile, mais il a rempli le code de pessimisations subtiles comme ci-dessus. Personnellement, je préfère adopter une politique générale de modification des variables aussi rarement que possible, et de rendre les fonctions suffisamment petites pour que l'utilisation d'une variable soit évidente, et même si elle est modifiée, la complexité de la fonction est suffisamment faible pour en faire un non -problème.


2
Votre point sur le déplacement montre où vous n'utilisez pas le local de manière constante, car vous (avez l'intention) de le modifier avec le déplacement
Caleth

1
@Caleth Non, c'est le point. Je n'ai pas l'intention de le modifier. Je veux juste passer la valeur, ou la retourner, et je veux qu'elle soit efficace. Conceptuellement, la modification n'est qu'une optimisation, qui n'est pas censée être observable (puisque les variables ne sont pas utilisées par la suite). En pratique, oui, il y a une modification, car C ++ n'a pas de véritables mouvements destructeurs (comme Rust). C'est exactement pourquoi je ne veux pas constsur les locaux: car cela empêche les modifications techniques, pas seulement les modifications conceptuelles.
Sebastian Redl

2
Vous ne voulez pas modifier la valeur , mais vous voulez modifier la variable . Vous pouvez plutôt utiliser const & à la place, et ne modifier ni l'un ni l'autre
Caleth

2

Le constmot-clé doit être utilisé pour les variables locales, tout comme les paramètres. C'est utile parce que:

  • Plus facile à lire le code. Lorsque quelqu'un lit la déclaration de variable, elle sait que cela ne changera pas. Une chose de moins à s'inquiéter lors de la lecture de votre code.
  • Vous empêcher de modifier accidentellement la variable
  • Aucune pénalité d'exécution, tout est vérifié statiquement. C'est comme un déjeuner gratuit, cela constne devrait prendre qu'une seconde pour écrire, donc ce n'est pas grave.
  • C'est toujours une bonne idée de faire vos variables / paramètres dans vos applications multi-thread. Même votre application n'est pas multi-thread, c'est toujours une bonne habitude.
  • Vous donnez à votre compilateur C ++ l'occasion d'optimiser votre code.

Notez qu'il n'y a pas de bonne / mauvaise réponse ici. Dans votre lien, le répondeur qui a soutenu le plus de votes positifs finalne doit pas être utilisé localement. Cependant, le répondeur suivant l'a fortement recommandé.

Si votre fonction est simple et triviale , vous ne devez pas en ajouter constcar tout le monde comprend votre intention. Cependant, si la logique de votre fonction n'est pas triviale, vous devez utiliser le mot clé. N'oubliez pas qu'il y a peu à perdre.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.