Home > Article > Backend Development > Why Does `B::getB()` Fail to Initialize `mB` in Templated Classes with Static Members?
In C , static member initialization for nested helper structs typically works without issues for non-templated classes. However, when the enclosing class is templated, a potential quirk arises if the helper object is not accessed in the main code.
Consider the following simplified example:
<code class="cpp">struct A { struct InitHelper { InitHelper() { A::mA = "Hello, I'm A."; } }; static std::string mA; static InitHelper mInit; static const std::string& getA(){ return mA; } }; template<class T> struct B { struct InitHelper { InitHelper() { B<T>::mB = "Hello, I'm B."; } }; static std::string mB; static InitHelper mInit; static const std::string& getB() { return mB; } static InitHelper& getHelper(){ return mInit; } };</code>
Here, the nested InitHelper initializes the static member mA for A and mB for B.
The issue arises when we try to initialize the members in a templated class B. Using the getB method, as shown below, does not trigger the initialization of mB:
<code class="cpp">std::cout << "B = " << B<int>::getB() << std::endl;
This happens because, according to the ISO/IEC C 2003 standard (14.7.1), the initialization of a static data member only occurs when the member is itself used in a way that requires its definition. In this case, since mB is only referenced in the getB() method of the templated class, the compiler does not implicitly instantiate its definition.
To understand the compiler's behavior, it is important to clarify the concept of implicit instantiation. For static data members in templates, an implicit instantiation instantiates the declarations but not the definitions. The actual initialization (constructor calls) happens only when the static data member is used in a manner that requires its definition (e.g., assignment).
On the other hand, explicit specializations use explicit declarations in namespaces or classes, which have ordered initialization. In other words, a specialized static data member is always initialized before any instantiation of its class template.
In your specific code example, calling B However, relying on the order of initialization is undefined behavior. The correct solution is to explicitly specialize the static data member mInit in class B. This will ensure that the helper object is always created and that any subsequent instantiation of B will have its static data members initialized correctly. To summarize, static member initialization in C templates requires careful consideration. Implicit instantiation only instantiates declarations, not definitions. For ordered and reliable initialization, explicit specialization should be considered when dealing with templated classes that contain static data members. The above is the detailed content of Why Does `B::getB()` Fail to Initialize `mB` in Templated Classes with Static Members?. For more information, please follow other related articles on the PHP Chinese website!Conclusion