Cela concerne principalement la deuxième ligne: meilleures pratiques, affectations, paramètres de fonction, etc.
Pratique générale. Essayez de faire tout ce const
que vous pouvez. Ou pour dire les choses autrement, faites tout const
pour commencer, puis supprimez exactement l'ensemble minimal deconst
s nécessaire pour permettre au programme de fonctionner. Ce sera une grande aide pour atteindre la const-correct, et aidera à éviter que des bogues subtils ne soient introduits lorsque les gens essaient de les affecter à des choses qu'ils ne sont pas censés modifier.
Évitez const_cast <> comme la peste. Il existe un ou deux cas d'utilisation légitimes, mais ils sont très rares. Si vous essayez de changer unconst
objet, vous ferez beaucoup mieux pour trouver celui qui l'a déclaré const
au premier rythme et en discuter avec eux pour parvenir à un consensus sur ce qui devrait arriver.
Ce qui mène très bien aux missions. Vous ne pouvez attribuer quelque chose que s'il n'est pas constant. Si vous souhaitez attribuer à quelque chose qui est const, voir ci-dessus. N'oubliez pas que dans les déclarations int const *foo;
etint * const bar;
différentes choses sont const
- d'autres réponses ici ont admirablement couvert cette question, donc je ne vais pas y entrer.
Paramètres de fonction:
Passez par valeur: par exemple, void func(int param)
vous ne vous souciez pas d'une manière ou d'une autre sur le site appelant. L'argument peut être avancé qu'il existe des cas d'utilisation pour déclarer la fonction commevoid func(int const param)
mais cela n'a aucun effet sur l'appelant, uniquement sur la fonction elle-même, en ce que la valeur transmise ne peut pas être modifiée par la fonction pendant l'appel.
Passez par référence: par exemple void func(int ¶m)
, cela fait maintenant une différence. Comme il vient d'être déclaré, il func
est autorisé de changer param
, et tout site appelant doit être prêt à faire face aux conséquences. Changer la déclaration pour void func(int const ¶m)
changer le contrat et les garanties qui func
ne peuvent plus changerparam
, ce qui signifie que ce qui est transmis est ce qui en ressortira. Comme d'autres l'ont noté, cela est très utile pour passer à bon marché un grand objet que vous ne voulez pas changer. Passer une référence est beaucoup moins cher que de passer un gros objet en valeur.
Passer par pointeur: par exemple , void func(int *param)
et void func(int const *param)
Ces deux sont à peu près synonyme de leurs homologues de référence, avec la mise en garde que la fonction appelée doit maintenant vérifier à nullptr
moins que d'autres assure la garantie contractuelle func
qu'il ne recevra jamais nullptr
dansparam
.
Article d'opinion sur ce sujet. Il est extrêmement difficile de prouver l'exactitude dans un cas comme celui-ci, il est tout simplement trop facile de faire une erreur. Alors ne prenez pas de risques et vérifiez toujours les paramètres du pointeur nullptr
. Vous vous épargnerez la douleur et la souffrance et vous aurez du mal à trouver des bogues à long terme. Et en ce qui concerne le coût de la vérification, c'est très bon marché, et dans les cas où l'analyse statique intégrée au compilateur peut le gérer, l'optimiseur l'élidera de toute façon. Activez Link Time Code Generation pour MSVC, ou WOPR (je pense) pour GCC, et vous obtiendrez tout le programme, c'est-à-dire même dans les appels de fonction qui traversent une limite de module de code source.
À la fin de la journée, tout ce qui précède constitue un cas très solide pour toujours préférer les références aux pointeurs. Ils sont tout simplement plus sûrs.