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 */