L'option g ++ -Wall inclut -Wreorder. Ce que fait cette option est décrit ci-dessous. Il n'est pas évident pour moi pourquoi quelqu'un s'en soucierait (surtout assez pour l'activer par défaut dans -Wall).
-Wreorder (C ++ uniquement) Avertir lorsque l'ordre des initialiseurs de membre donné dans le code ne fonctionne pas correspondent à l'ordre dans lequel ils doivent être exécutés. Par exemple: struct A { int i; int j; A (): j (0), i (1) {} }; Le compilateur réorganisera les initialiseurs de membres pour i et j en correspond à l'ordre de déclaration des membres, en émettant un avertissement effet. Cet avertissement est activé par -Wall.
c++
g++
compiler-warnings
Peeter Joot
la source
la source
-Werror=reorder
Réponses:
Considérer:
Maintenant
i
est initialisé à une valeur inconnue, pas zéro.Alternativement, l'initialisation de
i
peut avoir des effets secondaires pour lesquels l'ordre est important. Par exemplela source
i
est initialisé à1
). Ici,i
est initialisé àj
, ce qui démontre en fait un problème.Le problème est que quelqu'un peut voir la liste des initialiseurs de membres dans le constructeur et penser qu'ils sont exécutés dans cet ordre (j d'abord, puis i). Ils ne le sont pas, ils sont exécutés dans l'ordre dans lequel les membres sont définis dans la classe.
Supposons que vous ayez écrit
A(): j(0), i(j) {}
. Quelqu'un pourrait lire ça et penser que je finit par avoir la valeur 0. Ce n'est pas le cas, parce que vous l'avez initialisé avec j, qui contient des fichiers indésirables parce qu'il n'a pas lui-même été initialisé.L'avertissement vous rappelle d'écrire
A(): i(j), j(0) {}
, ce qui, espérons-le, semble beaucoup plus louche.la source
D'autres réponses ont fourni de bons exemples qui justifient l'option d'avertissement. J'ai pensé fournir un contexte historique. Le créateur du C ++, Bjarne Stroustrup, explique dans son livre Le langage de programmation C ++ (3e édition, page 259):
la source
Cela peut vous mordre si vos initialiseurs ont des effets secondaires. Considérer:
Ce qui précède affichera "bar" puis "foo", même si intuitivement on supposerait que l'ordre est tel qu'écrit dans la liste d'initialisation.
Sinon, si
x
ety
sont d'un type défini par l'utilisateur avec un constructeur, ce constructeur peut également avoir des effets secondaires, avec le même résultat non évident.Il peut également se manifester lorsque l'initialiseur d'un membre fait référence à un autre membre.
la source
L'avertissement existe car si vous venez de lire le constructeur, il semble qu'il
j
soit initialisé avanti
. Cela devient un problème si l'un est utilisé pour initialiser l'autre, comme dansLorsque vous regardez simplement le constructeur, cela semble sûr. Mais en réalité,
j
n'a pas encore été initialisé au point où il est utilisé pour l'initialisationi
, et donc le code ne fonctionnera pas comme prévu. D'où l'avertissement.la source