34 votes

Les appels de fonctions de la liste d'initialisation d'un constructeur sont-ils séquencés?

Considérer:

 int f () {
    static int i = 0;
    return i++;
}

struct Test {
    int a, b;
    Test () : a(f()), b(f()) {}
};

Test t;
 

Je sais que a est initialisé avant b raison de l'ordre de leur déclaration dans les struct .

Je sais aussi que les deux appels à f en g(f(), f()) sont pas séquencés.

Je me demande donc s'il est garanti que t.a == 0 et t.b == 1 ?

30voto

NathanOliver Points 10062

Alors je me demande si il est garanti qu' t.a == 0 et t.b == 1?

Ce sera toujours vrai tant que a "vient avant" b dans la déclaration de classe et rien d'autre appelle f() entre l'initialisation de a et b. Les membres de la classe sont initialisés dans l'ordre où elles sont déclarées dans la classe. [classe.de la base.init]/11:

Dans un non-la délégation de constructeur, de l'initialisation de produit dans l'ordre suivant: [...]

  • Alors, non les données membres statiques sont initialisés dans l'ordre où ils ont été déclarés dans la définition de la classe (encore une fois quel que soit l'ordre de la mem-initialiseurs).

Donc, depuis a "vient avant" b puis, quand le constructeur initialise a il appellera f() le premier temps et puis il va appeler une deuxième fois lorsqu'il initialise b.

Nous savons aussi il y a un point de séquence entre les membres de l'initialiseur parce que [la classe.de la base.init]/7:

[...]L'initialisation effectuée par chaque mem-initialiseur constitue une pleine expression. Toute expression dans un mem-initialiseur est évalué dans le cadre de la pleine expression qui effectue l'initialisation.

nous dit que chaque initialiseur est une expression pleine et entière et à chaque pleine expression est séquencé: [intro.exécution]/14

Chaque valeur de calcul et des effets secondaires associés avec une pleine expression est séquencée avant chaque calcul de la valeur et des effets secondaires associés à la prochaine pleine expression à évaluer.

6voto

R Sahu Points 24027

Je sais que a est initialisée avant b en raison de l'ordre de leur déclaration dans la structure.

C'est vrai.

Mon interprétation de cette contrainte est que l' a ne peut pas être initialisé avant d' b , sauf si l'évaluation de l'initialiseur expression est complet avant de l' b est initialisé.

Je ne vois rien dans la norme qui parle de séquençage de l'évaluation des expressions utilisées pour initialiser les membres non statiques. Cependant, je vois l'exemple suivant dans le Standard C++11 (12.6.2/12):

Noms dans l'expression de la liste ou calées-init-liste des mem-initialiseur sont évaluées dans le champ d'application du constructeur dont les mem-initialiseur est spécifié. [ Exemple:

class X {
  int a;
  int b;
  int i;
  int j;
  public:
  const int& r;
  X(int i): r(a), b(i), i(i), j(this->i) { }
};

Qui n'est pas valide à moins que l'évaluation de l' this->i est séquencé après i est initialisé.

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