Ordem de avaliação da lista de inicialização do construtor

252

Eu tenho um construtor que leva alguns argumentos. Eu supus que eles foram construídos na ordem listada, mas em um caso parece que eles estavam sendo construídos ao contrário, resultando em um abortamento. Quando eu invertai os argumentos, o programa parou de abortar. Este é um exemplo da sintaxe que estou usando. O problema é que a_ precisa ser inicializado antes de b neste caso. Você pode garantir a ordem de construção?

por exemplo

class A
{
  public:
    A(OtherClass o, string x, int y) :
      a_(o), b_(a_, x, y) { }

    OtherClass a_;
    AnotherClass b_;
};
Matt
fonte
6
Você diz que está perguntando sobre argumentos do construtor, mas eles são avaliados antes de você chegar ao construtor e são avaliados em uma ordem não especificada e determinada pelo compilador. Mas você está realmente perguntando sobre a ordem das listas de inicialização, então mudei o título da pergunta para você.
Rob Kennedy

Respostas:

278

Depende da ordem da declaração da variável de membro na classe. Então a_será o primeiro, então b_será o segundo no seu exemplo.

AraK
fonte
22
De fato, bons compiladores avisarão se você tiver uma ordem diferente na declaração em relação à lista de inicializadores do construtor. Por exemplo, veja -Wreorderem gcc.
Greg Hewgill 7/08/09
236
A razão pela qual eles são construídos na ordem de declaração de membro e não na ordem no construtor é que um pode ter vários construtores, mas há apenas um destruidor. E o destruidor destrói os membros na ordem inversa de construção.
AProgrammer 7/08/09
3
quis dizer ... ordem inversa da declaração. Não é de "construção", o destruidor não pode ver o construtor para saber, pode?
Conrad B #
196

Para citar o padrão, para esclarecimentos:

12.6.2.5

A inicialização deve prosseguir na seguinte ordem:

...

  • Em seguida, os membros de dados não estáticos serão inicializados na ordem em que foram declarados na definição de classe (novamente, independentemente da ordem dos inicializadores de mem).

...

GManNickG
fonte
18

A referência padrão para isso agora parece ser 12.6.2, seção 13.3:

(13.3) - Em seguida, os membros de dados não estáticos são inicializados na ordem em que foram declarados na definição de classe (novamente independentemente da ordem dos inicializadores de mem).

Adam Getchell
fonte