184 votes

Ce qui ' s le point de g ++ - Wreorder ?

Le g++ -Wall option comprend -Wreorder. Ce que cette option n'est décrite ci-dessous. Il n'est pas évident pour moi pourquoi quelqu'un aurait soins (surtout assez de désactiver cette sur par défaut dans la Paroi).

-Wreorder (C++ seulement)
 Avertir lors de la commande de membre des initialiseurs de la donnée dans le code n'est pas
 correspondent à l'ordre dans lequel elles doivent être exécutées. Par exemple:

 struct A {
 int i;
 int j;
 Un(): j (0), i (1) { }
};

 Le compilateur va réorganiser le membre initialiseurs pour i et j à
 correspondre à l'ordre de déclaration des membres, émettre un avertissement pour que
 effet. Cet avertissement est activé par -Mur.

305voto

int3 Points 6370

Tenir compte :

Maintenant `` est initialisé à une valeur inconnue, pas de zéro.

Par ailleurs, l’initialisation de `` peut avoir certains effets secondaires pour lesquels l’ordre est important. Par exemple

57voto

Steve Jessop Points 166970

Le problème, c'est que quelqu'un pourrait voir la liste des membres initialisers dans le constructeur, et de penser qu'ils sont exécutés dans l'ordre (j en premier, puis j'). Ils ne sont pas, elles sont exécutées dans l'ordre les membres sont définies dans la classe.

Supposons que vous avez écrit A(): j(0), i(j) {}. Quelqu'un peut lire que, et je pense que je termine avec la valeur 0. Ce n'est pas, parce que vous avez initialisé avec j, qui contient indésirable, car il n'a pas été initialisé.

L'avertissement vous rappelle de vous écrire A(): i(j), j(0) {}, qui nous l'espérons semble beaucoup plus attirants.

30voto

gkb0986 Points 391

D'autres réponses ont fourni quelques bons exemples qui permettent de justifier l'option pour un avertissement. Je pensais fournir certaines contexte historique. Le créateur du langage C++, Bjarne Stroustrup, explique dans son livre Le langage de programmation C++ (3e édition, Page 259):

Les membres les constructeurs sont appelés avant que le corps de la classe conteneur propre constructeur est exécuté. Les constructeurs sont appelés dans l'ordre dans lequel elles sont déclarées dans la classe plutôt que dans l'ordre dans lequel ils apparaissent dans la liste d'initialiseur. Pour éviter toute confusion, il est préférable de préciser les initialiseurs dans l'ordre de déclaration. Le membre destructeurs sont appelés dans l'ordre inverse de la construction.

13voto

Pavel Minaev Points 60647

Cela peut vous mordre si votre initialiseurs d'avoir des effets secondaires. Considérer:

int foo() {
    puts("foo");
    return 1;
}

int bar() {
    puts("bar");
    return 2;
}

struct baz {
    int x, y;
    baz() : y(foo()), x(bar()) {}
};

Le ci-dessus permettra d'imprimer "de la barre", puis "foo", même si, intuitivement, on peut supposer que la commande est aussi écrit dans la liste d'initialiseur.

Sinon, si x et y sont d'un type défini par l'utilisateur avec un constructeur, constructeur peut également avoir des effets secondaires, avec le même résultat.

Il peut également se manifester lors de l'initialisation d'un de ses membres fait référence à un autre membre.

8voto

jalf Points 142628

L'avertissement n'existe que parce que si vous vous contentez de lire le constructeur, il ressemble j est prise en initialisé avant d' i. Cela devient un problème si l'un est utilisé pour initialiser les autres, comme dans

struct A {
  int i;
  int j;
  A(): j (0), i (this->j) { }
};

Lorsque vous venez de regarder le constructeur, cela ressemble fort. Mais en réalité, j n'a pas encore été initialisé au point où il est utilisé pour initialiser i, et donc le code ne fonctionne pas comme prévu. D'où l'avertissement.

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