C ++: estático na inicialização dependente da variável de membro estático com int vs struct

Dada uma variável de membro estático que é inicializada a partir de uma variável de membro estático deoutra classe, o não literalstruct ii às vezes é inicializado como padrão0 ou para333. Isso depende da ordem de compilação ou vinculação.Pseudo-código para demonstrar:

class StaticClass: // file 'ONE.cpp/.hpp'
    static int i = 2
    static struct ii { int a = 333 }

class ABC: // file 'abc.cpp'
    static int abc_i = StaticClass::i   // always 2
    static struct abc_ii = StaticClass::ii // sometimes 0, sometimes 333

Chamandog++ -std=c++11 abc.cpp ONE.cpp && ./a.out resulta emi = 2 / ii = 0 (gcc 4.8.1, mesmo com clang ++ 3.7;-Wall -Wextra nunca reclame).

Mas chamandog++ -std=c++11 ONE.cpp abc.cpp && ./a.out resulta emi = 2 / ii = 333 !

O mesmo acontece comONE.o abc.o vsabc.o ONE.o e também ao concatenar os arquivos de uma maneira ou de outra:

cat ONE.cpp abc.cpp > X.cpp && g++ X.cpp && ./a.out vscat abc.cpp ONE.cpp > Y.cpp && g++ Y.cpp && ./a.out

Removendo as inclusões e movendo o código no arquivo único, a inicialização padrão para 0 acontece quando esta ordem está presente:

const OneI ABC::def_ii = StaticClass::ii; const OneI StaticClass::ii = OneI{333};

e o de 333 com esta ordem:

const OneI StaticClass::ii = OneI{333}; const OneI ABC::def_ii = StaticClass::ii;

Por que isso acontece com duas unidades de compilação separadas? Isso pode ser evitado de alguma forma, impondo o último pedido o tempo todo? Está usando um ponteiro estático noABC paraStaticClass::ii seguro (eu preferiria não fazer isso)?

Código C ++ completo:

/* File: abc.cpp */

#include <iostream>
#include "ONE.hpp"

struct ABC {
  ABC();

  static const int def_i;
  static const OneI def_ii;
  void arg_i(const int &x) { std::cout << "i = " << x << " ";};
  void arg_ii(const OneI &x) { std::cout << "/ ii = " << x.a << " ";};

};

ABC::ABC() {
  arg_i(def_i);
  arg_ii(def_ii);
}

const int ABC::def_i = StaticClass::i;
const OneI ABC::def_ii = StaticClass::ii;

int main() {
  ABC a;
  std::cout << '\n';
}
/* End: abc.cpp */
/* File: ONE.cpp */

#include <iostream>

#include "ONE.hpp"

const int StaticClass::i = 2;
const OneI StaticClass::ii = OneI{333};

/* End: ONE.cpp */
/* File: ONE.hpp */

#include <iostream>

#ifndef One
#define One

struct OneI {
  OneI(int a_) : a(a_) { }
  int a;
};

struct StaticClass {
  const static int i;
  const static OneI ii;
};

#endif // One header guard

/* End: ONE.hpp */

questionAnswers(1)

yourAnswerToTheQuestion