Je connais le problème de l’ordre d’initialisation des variables statiques provenant de différentes unités de traduction. Cependant, mon problème est dans une unité de traduction et, en fait, dans une structure:
template struct SlidingTile { using AllActions = std::array; using AllMDDeltas = std::array; int mdDelta(int i) const { return mdDeltas_[i]; } static AllActions computeAllActions() { std::cout << "computeAllActions" << std::endl; AllActions res; for (int i = 0; i < size; ++i) res[i] = i; return res; } static AllMDDeltas computeAllMDDeltas() { std::cout << "Entered computeAllMDDeltas" << std::endl; AllActions res; for (int i = 0; i < size; ++i) res[i] = 10 * allActions_[i]; std::cout << "Exiting computeAllMDDeltas" << std::endl; return res; } private: static const AllActions allActions_; static const AllMDDeltas mdDeltas_; }; template const typename SlidingTile::AllActions SlidingTile::allActions_ = SlidingTile::computeAllActions(); template const typename SlidingTile::AllMDDeltas SlidingTile::mdDeltas_ = SlidingTile::computeAllMDDeltas(); int main() { SlidingTile s; std::cout << s.mdDelta(2) << std::endl; return 0; }
La sortie est:
Entered computeAllMDDeltas Exiting computeAllMDDeltas computeAllActions
À ma grande surprise, computeAllMDDeltas
est appelé avant computeAllActions
. allActions_
conséquent, allActions_
n’est pas initialisé lorsqu’il est utilisé dans computeAllMDDeltas
. Fait intéressant, computeAllActions
n’est pas appelée même lorsque allActions_
est utilisé dans computeAllMDDeltas
.
Pourquoi cela se produit-il et quelle est la méthode conseillée dans cette situation?
Comment se fait-il que l’ordre de définition ne soit pas suivi lors de la définition de variables de membre statique?
Parce que la norme dit que l’initialisation n’est pas ordonnée:
[basic.start.init] / 2 (projet de norme N4140)
… Les définitions des membres de données statiques de modèle de classe explicitement spécialisés ont ordonné leur initialisation. Les autres membres de données statiques de modèle de classe (c’est-à-dire les spécialisations implicitement ou explicitement instanciées) ont une initialisation non ordonnée . …
Quelle est la manière conseillée dans cette situation?
Identique à l’initialisation sur plusieurs unités de traduction: Construire lors de la première utilisation idiome:
struct SlidingTile { // ... private: static const AllActions& allActions() { static const AllActions instance = computeAllActions(); return instance; } static const AllMDDeltas& mdDeltas() { static const AllMDDeltas instance = computeAllMDDeltas(); return instance; } };