Is the initialization order guaranteed

I use something like the following sections of code to initialize. I know that the initialization p<T>::i_ unordered. I believe that h ordered, so I should be able to reason about in which order it is initialized. Given that the header for p included before the definition of h , is there any guarantee that p<T>::i_ will be initialized to h ?

 struct helper { template <typename T> helper(const T&, int i) { p<T>::i_::push_back(i); } }; static helper h; 

The class p is defined below.

 template <typename T> struct p { static std::vector<int> i_; }; template <typename T> std::vector<int> p<T>::i_; 
+4
source share
3 answers

The order of initialization of objects with static storage duration undefined between translation units and the sequence within each translation unit.

In your particular case, everything is more complicated, since one of the objects with static storage is a static member of the template class. In practice, this means that each translation unit that refers to the p<T>::i_ element will create a character and add the appropriate initialization code. The linker will later select one of the instances and save it. Even if it looks like this: p<T>::i_ defined to h in your translation unit, you donโ€™t know which instance of p<T>::i_ will be stored by the linker, and it can be one in another translation unit and, therefore The order is not guaranteed.

In general, it is a bad idea to have global objects; I would suggest you redesign your program without these global variables.

+6
source

Objects in a global or namespace space are constructed from top to bottom within a single translation unit. The order of building a global level or namespace between different translation units is not defined. The smartest way to streamline initialization between translation units is to wrap objects in appropriate access functions, for example:

 template <typename T> something<T>& get() { static something<T> values; return value; } 

Please note, however, that this is not thread safe in C ++ 03 (since C ++ 03 has no concept of threads). It is thread safe in C ++ 11.

+5
source

No, this is not guaranteed.

However, you can:

 template<typename T> std::vector<int>& registry() { static std::vector<int> reg; return reg; } ... registry<T>().push_back(i); ... 

It is even better to avoid doing things that are too smart during startup.

Debugging before or after main is a true nightmare (and IMO doesn't even cover 100% in the standard). A simple registration may be fine, but never do anything that can fail.

Over the years, I have moved away from this approach to explicit initialization / shutdown and have never looked back.

0
source

Source: https://habr.com/ru/post/1499221/


All Articles