0

So I’m working on a project that has two const arrays of two classes (classes A and B). The class A array needs access to the class B array while initializing, but the B array always returns nullptr, which is a big problem. Perhaps it would be easier to see the code (heavily simplified because the actual classes are huge and most of the info is irrelevant here):

// A.h
#pragma once
#include <vector>
#include "B.h"
#include "B_ARRAY.h"

class A
{
private:
    int bOffset; // the array offset of the corresponding element in B_ARRAY
    std::vector<int> otherInfo; // other info, which determines the corresponding B_ARRAY element
public:
    A(std::vector<int> i) : otherInfo(i)
    {
        bOffset = -1;
        while (bOffset == -1)
        {
            // search algorithm for the corresponding element in B_ARRAY
        }
    }
    
    B* getB()
    { return B_ARRAY[bOffset]; }
}
// B.h
#pragma once
#include <vector>

class B
{
private:
    std::vector<int> info;
public:
    B(std::vector<int> i) : info(i)
    {}
    
    std::vector<into> getInfo()
    { return info; }
}
// B_ARRAY.h
#pragma once
#include "B.h"

const int B_LENGTH = 900;

B* const B_ARRAY[B_LENGTH] = 
{
    new B(std::vector<int>({...})),
    new B(std::vector<int>({...})),
    [...]
};
// A_ARRAY.h
#pragma once
#include "A.h"

const int A_LENGTH = 1200;

A* const A_ARRAY[A_LENGTH] = 
{
    new A(std::vector<int>({...})),
    new A(std::vector<int>({...})),
    [...]
};

While it's searching in the A constructor, B_ARRAY[x] is always nullptr, which makes B_ARRAY[x]->getInfo() fail. In main(), it works just fine, so I assume this means B_ARRAY isn't fully initializing until main(). What do I have to do to make sure it fully initializes before A_ARRAY?

I could make a B object as a member of the A class, but a lot of A classes end up with identical Bs (in my current code, I'd want them to reference the same B object), and both of the actual constructor calls are already long enough as it is, so splitting them over two arrays helps keep it organized.

KRLW890
  • 63
  • 1
  • 8
  • Does this answer your question? [C++ global initialization order ignores dependencies?](https://stackoverflow.com/questions/3746238/c-global-initialization-order-ignores-dependencies) – Lev Leontev Feb 02 '22 at 20:28
  • 1
    This problem is more commonly known as the [static initialization order fiasco](https://stackoverflow.com/questions/29822181/prevent-static-initialization-order-fiasco-c). – Drew Dormann Feb 02 '22 at 20:29
  • What `.cpp` files do you have and how _exactly_ do they include the header files? – user17732522 Feb 02 '22 at 20:39
  • But in any case, I don't think there is any reason to use `new` here. Just have `A_ARRAY` and `B_ARRAY` be arrays of `std::vector`s directly. – user17732522 Feb 02 '22 at 20:48

1 Answers1

1

See, for instance, Static variables initialisation order.

"C++ guarantees that variables in a compilation unit (.cpp file) are initialised in order of declaration. For number of compilation units this rule works for each one separately (I mean static variables outside of classes). But the order of initialization of variables is undefined across different compilation units."

So you can either initialize all the static vars in one source file, or restructure the code to not depend on that order.

GaryO
  • 5,873
  • 1
  • 36
  • 61
  • I don't think this should apply here. In the question all global variables are `const` qualified, meaning they have internal linkage. Also, it wasn't shown that there are even two translation units. – user17732522 Feb 02 '22 at 20:40
  • True; OP may be including all 4 headers in one `.cpp`. But in that case the solution would be trivial; just `#include` them in the right order. I expect OP would not be posting here in that case. – GaryO Feb 02 '22 at 21:11