12
votes

Quel est le problème avec const?

Quels sont les déficits connus de const en C ++ et c ++ 0x?


11 commentaires

Je pense qu'ils sont utiles car rendent le code plus facile à comprendre.


Besoin d'indiquer une question avant que vous obtiendrez votre réponse,


Le seul problème que je vois avec const est que son état de préparation et Effets varie considérablement en fonction du niveau du programmeur C ++ (une certaine confusion sur quel élément const < / code> s'applique dans une déclaration complexe, par exemple). En plus de cela fait partie de la langue et doit être utilisé - tant que le livre de B.Stroustrup a été lu :-)


@Vilx Ne pensez-vous pas que "alors que (x


Intéressant de voir combien de fois cette question est fermée et rouvert.


@David: On dirait une question pour moi.


voté pour rouvrir. Question utile définitivement. Dommage que nous ne puissions pas y arriver à la communauté wiki. Ce n'est certainement pas une question non-CW. IIRC, une règle de base est la suivante: si par nature, il ne peut pas avoir une "réponse acceptée", elle devrait être cw.


@Tomalak C'est plus une question maintenant que cela a été édité!


@David: Je ne vois aucune modification. Peut-être que c'était trop rapide.


@Tomalak: Il a été édité une trentaine secondes après avoir été mise en place. Je trouve franchement la réponse à cette question hilarante, car il y a une question exactement identique à propos de ADL que personne ne veut voter pour fermer.


@Deadmg Je ne comprends pas le vote à proximité non plus.


12 Réponses :


58
votes

La seule chose qui ne va pas avec const est qu'il est sérieusement sous-estimé par de nombreux développeurs. C'est l'un des meilleurs outils de la boîte à outils de C ++, très forte, et pourtant pas dangereux de vous couper.


1 commentaires

"Mais qu'est-ce qui a fait de ceux qui m'avaient ri d'arrêter de rire étaient quand, après plusieurs jours, il est devenu évident que plusieurs très difficiles à reproduire des bugs que quelques-uns de mes collègues recherchaient désespérément avaient disparu." (de chat )



1
votes

"Problèmes"?

Si vous n'allez pas modifier la valeur d'un pointeur transcuté (il est utilisé uniquement pour une entrée passe-par-référence à une fonction), marquez-le est const . Idem si la valeur d'une variable particulière ne changera pas après son initialisation. Si une fonction est sécuritaire d'appeler sur une instance de classe const , marquez-le const aussi. Plus les articles sont correctement annotés Const , moins vous êtes susceptible de faire une erreur par inadvertance et des optimisations du compilateur seront théoriquement capables de fonctionner en l'absence de connaissances complètes (telles que la compilation avec seulement Prototypes de fonction disponibles).

Les versions modernes de GCC ont pris en charge l'avertissement lorsque vous essayez de lancer une variable const à un non- const un. Je vous suggère de laisser ces avertissements activés.

La seule chose à surveiller est exactement quel vous marquez const ; Const Char * FOO () n'est pas le même que char * foo () const .


1 commentaires

Je ne demande pas comment utiliser const. Je sais déjà comment utiliser const. Je cherchais problèmes avec const.



3
votes

Le problème avec const est les programmeurs qui l'utilisent de manière incorrecte notre inconventionnement


0 commentaires

16
votes

Les deux principaux problèmes que j'ai connus de fréquents plaintes concernant les groupes de discussion, sont


14 commentaires

Quelles API Microsoft ne sont pas-Cons-Cons-ci? IIRC L'API Windows utilise LPCTSTRS, MFC utilise Const correctement IIRC, etc. Je ne peux penser à aucun.


@Rup: aurait besoin de beaucoup de recherches qui les traversent tous. Je rapporte ce que les gens se sont plaints, mais je peux confirmer une expérience propre. S'il n'y avait que quelques fonctions problématiques, je me souviendrais peut-être des noms, mais tout est fini.


@Rup: De nombreuses API Microsoft n'utilisent pas beaucoup de const. Quand était la dernière fois que vous avez vu une poignée constante? Ou un const iDirect3Ddevice9 *? Microsoft utilise Const pour les chaînes et c'est à ce sujet.


@Deadmg: A Poignée est un objet opaque que vous ne pouvez pas modifier de toute façon sans utiliser les fonctions de l'API. Pour les interfaces COM, ils utilisent des attributs tels que [in] et [out] . Et pour la plupart des autres types C, ils utilisent const .


Peut-être que ce n'est pas purement win32 mais com btr ne peut pas être un const (puisqu'il s'agit d'un Typedef qui ne permet pas de mettre le const sur la partie correcte du type).


@Philipp: Vous pouvez modifier le la poignée juste bien; Vous ne pouvez pas facilement modifier la chose que cela finit par pointer. poignée étant const aiderait à éviter les personnes d'oublier cela.


+1 pour "la nécessité de définir la version de const et non constitue d'une méthode". !


@LitB Ah j'ai raté que sur ma première lecture. +1 de moi aussi pour ça.


@Tomalak Notez que "@name" en informera l'utilisateur uniquement si remplacer (, "" "," ") commence par" Nom ". Donc, "@joh" m'informerait de votre commentaire et "@johannesschaub" serait aussi. Mais "@litb" ne :( :(


@Johannesschab: Peut-être que je me cache: p (ok)


Que voulez-vous dire par const ne pas se propager à posséder des objets possédés? Si vous tenez une référence constante à une structure, tous les membres sont également considérés comme constants. Vous avez même le mot clé mutable pour permettre la mise en œuvre des caches (c'est-à-dire qu'il n'a pas d'impact sur la sortie si cette variable change).


@Pierrebdr: Je pense que ce qu'ils veulent dire, c'est qu'un membre int * est vu comme int * cons (et pas int const * ) de l'intérieur une fonction membre de Const. En conséquence, ce qu'il pointe pour peut toujours être changé.


@Alf: Pouvez-vous ajouter des liens relatifs au "besoin d'ajouter les versions de const et non const"?


@Richard: C ++ FAQ est un bon point de départ. J'ai fait un peu de google et j'ai découvert que de nombreuses autres ressources sont obsolètes, y compris une gotw par Sutter d'herbes, liée à partir de La page Wikipedia sur la correction de const . Herb's Gotw conseille "lors de l'utilisation de la valeur de retour pour non -Builtine Types de retour, préférez renvoyer une valeur de const », raisonnable dans sa journée, mais avec laquelle avec Mojo ou C ++ 0x empêche« déménager »efficace.



-1
votes

Un problème est que la langue vous permet également de const_cast, ce qui défait le but d'utiliser Cons en premier lieu.


10 commentaires

pas vraiment comme vous ne pouvez le jeter explicitement et vous devez évidemment être capable de const_cast pour soutenir les API hérités


Non plus ... const serait inutile sans la possibilité de la jeter, car dans le code du monde réel, vous devez traiter des APIS écrites par les programmeurs qui ne font pas ' T Comprendre la constance Constance (ou le retour dans une heure était const ne faisait pas encore partie de C ++).


@Fredoverflow Je vois ... Je n'avais jamais rencontré cette situation auparavant. Merci pour la clarification.


@JK Le problème que j'ai rencontré est lorsque j'ai une fonction Const et un autre développeur Const_cast l'emporte, ce qui a vaincu l'intégralité du point de le faire en premier lieu. Au moins c'est mon souvenir.


@Fredoverflow: Mais peut-être que ce serait une bonne chose si ces programmeurs étaient chassés et tués par des personnes qui ne peuvent plus travailler autour de leur code brisé par la conscience? ;-) En ce qui concerne le code antique - Quelque chose peut toujours être un déficit de la langue même si la motivation du déficit est de soutenir le code pré-standard et / ou les conventions. Par exemple, vous pouvez penser que la conversion automatique sur VOID * est un déficit de C ++: il est nécessaire pour E.G. std :: memcpy , mais dans le contexte de C ++, les fonctions ne doivent pas être conçues pour accepter silencieusement tout pointeur indépendamment de la sécurité de type.


@Dave: Pourquoi Le développeur a-t-il jeté-la. La plupart des cases sont diaboliques et / ou inutiles. Si vous ne faites pas confiance aux programmeurs, C ++ est la mauvaise langue.


@Fredoverflow Il était obligé de nécessiter un comportement particulier qu'il souhaitait, mais au détriment de tout le reste. Le changement n'a jamais fait passer, cependant. :)


@Steve: Comment les tuerait-il maintenant résoudre le problème? Laissez les fichus terminateurs faire le travail à fond et essuyer les non-croyants de l'histoire!


Non, bien que const_cast est légal, écrit à un objet-créé- Const (même si vous avez éliminé la constance sur la variable ) n'est pas légal.


(Cela dit, bien sûr, ce serait bien si const_cast n'a même pas existé. C'est un piratage et peut facilement conduire à l'illégalité que je décris ci-dessus.)



18
votes

Qu'est-ce qui ne va pas avec Const est que de nombreux programmeurs ne semblent pas être capables de le comprendre complètement et qu'un projet "demi-constance" ne fonctionne tout simplement pas. C'est ce que vous devez savoir:

  1. foo vs. code> const foo (ou foo const )
  2. foo & vs. code> const foo & (ou foo const & )
    • Références-to-const lier à toutes sortes de choses, tandis que les références à la non-const ne font pas
    • foo * vs. code> const foo * (ou foo const * )
      • Les variables de pointeur peuvent également être foo * const et const foo * const (ou foo const * const )
      • void foo :: mutateur () vs. code> int foo :: accessor () const
        • Mais les membres du pointeur à l'intérieur des fonctions membres de consons pointent toujours sur des objets non-consonsts
        • Nous pouvons donc renvoyer accidentellement les données non-Const d'une fonction constante
        • itérateur vs. code> const_iterator
          • Les variables itératrices peuvent également être const itérateur et const const_iterator (code>

            Migration en C ++ à partir d'une langue qui n'a aucun concept Const est assez difficile, de nombreux échecs pour voir le point.


7 commentaires

NIT-Cueillette: Les références aux objets ne peuvent pas être constituées, mais les références peuvent faire référence à des objets constants. (La plupart des gens savent ce que vous voulez dire, mais la distinction est plus importante avec les pointeurs, où nous avons à la fois des indicateurs de const et des indications à Const.)


@Phil: Droite, j'ai changé les pièces pertinentes de l'anglais vers C ++ ;-)


Que de nombreux programmeurs ne comprennent pas que ce n'est pas un problème avec const . C'est un problème avec les programmeurs et l'état sérieusement pathétique d'éducation de programmation dans le monde occidental.


@Chris: Merci d'avoir attrapé ça!


La question ne demande pas comment utiliser const. Je sais déjà comment utiliser const. La question concerne les inconvénients de la const.


Bonne dégagement des utilisations de Cons Fred, mais où puis-je trouver une bonne référence sur les cas d'utilisation donnés? Je suis nouveau à l'idée que const peut économiser beaucoup de bugs, mais j'ai besoin d'une compréhension approfondie de celle-ci avant utilisation. J'espère que quelqu'un peut aider avec un bon tutoriel / liens


@Overtheedge Je vous suggère d'acheter "efficace C ++" (3ème édition) de Scott Meyers. L'élément 3 consacre 10 pages au sujet.



50
votes

Le problème principal est que vous devez l'écrire. Il devrait être la valeur par défaut, et toutes les variables ou paramètres mutables doivent être spécifiés explicitement.


10 commentaires

Ne peut pas uplifier cela assez. Même si (ou parce que), cela ferait des ravages avec la plupart des idées préconçues des programmeurs.


Sauf pour deux choses: la majorité des variables sont créées pour être écrites. Les avoir tous en lecture seule par défaut crée plus de travail. De plus, la philosophie de la langue C et C ++ est que le programmeur sait ce qu'ils font et que la langue ne devrait pas vous empêcher de faire ce que vous voulez.


@Jay "La majorité des variables sont créées pour être écrites." - une fois . Je modifie rarement la valeur d'une variable après sa première affectation (les conteneurs sont une sorte d'exception).


Vous n'allez jamais trouver que l'une ou l'autre est meilleure. Certains objets que vous créez pour la lecture / écriture (comptoirs en boucle, itérateurs, conteneurs, flux, la plupart des chaînes) et d'autres que vous ne vous attribuez à une fois - en fait, je ne peux penser à aucun exemples pour celui-ci. Pourquoi votre ponctuel écrit-t-il des initialisations non constantes?


Wow, j'ai totalement manqué votre réponse lorsque j'ai écrit le mien (maintenant supprimé, disait la même chose). Une des raisons que j'ai supprimées le mien est que je ne peux pas imaginer que c'est une valeur irrégulière pour les variables locales. Mais je peux définitivement imaginer qu'il est sain d'esprit de paramètres de valeur. Donc, peut-être faire des paramètres const par défaut, sauf si vous mettez le mot clé "mutable"?


De nombreuses variables de membre de classe sont initialisées uniquement dans le constructeur, puis ne changent jamais de la durée de vie de la classe. J'ai parfois changé ma politique pour rendre ces const et public, plutôt que non-consistant, privé avec des getters publics. Je sais que beaucoup de gens n'aiment pas le concept de membres publics et, s'ils sont non-consons, je suis d'accord, mais si elles sont je ne vois pas la question.


@JOH: J'ai généralement const variables locales aussi. Bien sûr, la question est beaucoup plus petite: cela n'aide pas en ce qui concerne la constance, mais contribue à la recherche d'erreurs.


@Philipp: Phew, je suis content que je ne sois pas le seul à faire des variables locales const . :)


-1 De moi j'ai peur. Comme le suggère qu'il s'agisse d'une défaillance raisonnable pour les paramètres de fonction, mais il est rare que je reçoive une variable locale dont la valeur reste fixée après son attribution initiale. C ++ est une langue impérative; Il n'y a pas de honte à l'attribution de deux fois :)


@J_RANDOM: C ++ est une langue multi-paradigme et, par exemple, prend en charge de plus en plus la programmation fonctionnelle. Je me trouve sur des données mutables de moins en moins au fil des ans et de faire tout ce que const par défaut.



3
votes

Une chose qui est « mauvais » est que vous ne pouvez pas convertir T ** à T const * const * qui devrait être autorisé car il est dangereux. Ne pas permettre à T ** pour convertir en T const ** est correct, que la conversion n'est pas valide.

Je l'ai parfois mentionné que const est en fait un moyen pas cher de « diviser » l'interface sur les méthodes et les méthodes d'écriture en lecture seule. Il serait probablement peu pratique en C ++. Il serait plus pratique en Java pour avoir des versions ReadOnly des collections cependant, où ils ne sont pas const et où leurs types de collections sont plus orientées objet.

constness ne se propage pas: La question ici est que si je Pimpl ma classe, la constness n'est pas « vérifié » par le compilateur, à savoir ma classe d'interface peut avoir un appel de méthode « const » une méthode non-const sur le Pimpl et le compilateur ne se plaindront pas. C'est parce que la seule chose que ma méthode const est garanti de ne pas faire est de changer le pointeur pour pointer vers un objet différent, et mon Pimpl ne va jamais changer. Il pourrait même être un pointeur const (pas de pointeur sur const).

L'absence de co-variance appropriée entre shared_ptr et shared_ptr peut être un problème aussi, bien qu'en général j'ai vu que de ne pas le problème, mais que les développeurs généralement typedef leurs shared_ptrs et rarement typedef la shared_ptr à const. Et ils parfois passer const shared_ptr & et penser qu'ils passent un pointeur partagé à un T const (comme const T *) qu'ils ne sont pas.


3 commentaires

"Impossible de convertir t ** t ** sur t const * const * " - Cette partie est fausse (au moins avec les compilateurs que j'utilise); Je me souviens que c'était une gêne dans C mais C ++ a eu raison.


Vous pouvez avoir une vérification constante de la classe PIMPL, pas de gros problème ... Par exemple, regardez l'utilisation QTS des classes PIMPL .. (Ils utilisent 2 fonctions privées PIMPL-Accessor (Const / NonConst) pour accéder à l'objet PIMPL, si vous le souhaitez. Pour vous assurer que vous n'accédez pas à l'objet PIMPL sans utiliser ces fonctions (et de contourner ainsi la Const-Check), vous pouvez utiliser un video entièrement opaque Void * pour l'objet PIMPL et ajouter des réinterpret_casts à l'acesseur. Fonctions (examinez l'implémentation de IE Q_Declare_private)


@Anatolyg: Vous êtes correct. Le premier paragraphe ne décrit pas quelque chose de "faux" avec const car ce n'est pas vrai. Voir 4.4 [Conv.Qual] / 4 de ISO / CEI 14882: 2003.



-2
votes

Une chose est que cela reste possible le subvert. C'est-à-dire qu'il est toujours légal de faire quelque chose comme ceci: xxx

Vous pouvez même utiliser des éléments tels que Memset pour l'interversion sans un const_cast .

Il s'agit d'un compromis entre le compilateur appliquant const et permettant une certaine flexibilité pour les interfaces de conscons const

Ce qui conduit à une autre limitation, en ce sens qu'il n'a pas été universellement adopté, ce qui est en partie dû à un autre problème, ce qui consiste à utiliser const est une proposition tout-ou-rien. Si vous commencez à l'utiliser, vous devrez le propager tout au long de votre base de code.


3 commentaires

Non, c'est peut-être un comportement non défini (si l'objet d'origine a été créé const ) et dans le contexte de cette fonction doit être supposé être. Un const_cast est légal, mais écrit à un objet créé comme const , que vous ayez déposé la constance ou non, est illégal.


Eh bien, oui, mais si vous pensez être constitué d'un contrat ou d'une promesse que je ne le changerai pas (même s'il s'agissait de non-cons autres auparavant), il est possible de le casser.


Mais vous pouvez faire des promesses sous forme de commentaires dans chaque langue, puis les subverver. const est un outil non-commentaire / intégré qui vous oblige à ne pas casser le contrat par défaut , alors que dans les langages non-constants, vous pouvez changer accidentellement quelque chose de documenté invariant.



0
votes

Un autre problème qui n'a pas encore été mentionné est la possibilité d'une interface mal conçue pour subverver const (même en l'absence de moulages).

Exemple: P>

class TreeNode {
public:
    TreeNode& getParent() const { return *parent_; }
    TreeNode& getLeft()   const { return *left_;   }
    TreeNode& getRight()  const { return *right_;  }
private:
    //TreeNode has a pointer to the Tree to enable navigation of the tree.
    //Assume that other design constraints mean that this must be a pointer 
    //rather than a reference.
    TreeNode* parent_;
    TreeNode* left_;
    TreeNode* right_;
};
//This function demonstrates the ability for const to be subverted.
TreeNode& remove_const(TreeNode const& toRemoveConstFrom) {
    TreeNode& parent(toRemoveConstFrom.getParent());
    TreeNode& leftChild(parent.getLeft());
    TreeNode& rightChild(parent.getRight());
    return &toRemoveConstFrom == &leftChild ? leftChild : rightChild;
}


0 commentaires

0
votes

La plupart des réponses ci-dessous des choses d'état tels que "Qu'est-ce qui ne va pas avec const est que X Les gens font Y". Ce ne sont pas des réponses mais symptômes . Ce ne sont pas un problème avec const . Il y a à peine toute mauvaise chose avec const ... Ce sont des choses mal avec des personnes qui ne peuvent pas ronger .


0 commentaires

0
votes

const est génial. const est important. const -Correcness est nécessaire conditionner pour qu'une API soit bonne.

Pourtant, il y a deux problèmes que j'ai eu avec const , à plusieurs reprises.

  • Il n'y a aucun moyen de marquer une variable comme const rétroactivement. Vous devez soit déclarer un code variable, auquel cas vous avez pour l'initialiser immédiatement. Et si le code d'initialisation contient un si , cependant? Vous avez le choix d'omettre l'omission du const (indésirablement), à l'aide de l'opérateur ? au lieu de si (nuit à la lisibilité). Java obtient ce droit, BTW - const Les variables ne doivent pas être initialisées tout de suite, ils doivent simplement être initialisés avant ils sont d'abord lus, et ils doivent être initialisé dans tous les succursales d'un si .

  • Il n'y a aucun moyen de spécifier qu'un objet adopté par référence à une fonction ne changera pas pendant la durée de l'appel de la fonction. const t & t ne signifie pas signifie que l'objet pointé par t ne changera pas, mais seulement que la référence t ne peut pas être utilisé pour le changer. Le compiller doit toujours supposer que tout appel de fonction qu'elle ne voit pas dans pourrait changer l'objet. Certains cas empêchent de nombreuses optimisations.


0 commentaires