There is plenty of information on when constructors of static members of ordinary classes are called. However, I am seeing some strange behavior with regard to template classes.
What should the output of the following program be? (Note I use printf to avoid any static initialization order fiasco complications with std::cout.)
#include <iostream>
class B {
public:
B(const std::string &s) { printf("Hello I am B from %s\n", s.c_str()); }
};
template<typename T>
class Atempl {
public:
static B b_;
};
class A {
public:
static B b_;
};
template<typename T>
B Atempl<T>::b_("Atempl");
B A::b_("A");
class C : public Atempl<int> {
};
int main(int argc, const char *argv[]) {
return 0;
}
I think the output should be:
Hello I am B from A
Hello I am B from Atempl
But with g++ 4.3 on FreeBSD 7.3 I get:
Hello I am B from A
If I add the line
template class Atempl<int>;
all is well and I get the expected output. The question is, why doesn't the declaration of class C count as an instantiation of the template Atempl and cause B's constructor to be called? Is this part of the standard or a bug in g++ 4.3?
A static constructor is called automatically. It initializes the class before the first instance is created or any static members declared in that class (not its base classes) are referenced. A static constructor runs before an instance constructor.
We can put static members (Functions or Variables) in C++ classes. For the static variables, we have to initialize them after defining the class. To initialize we have to use the class name then scope resolution operator (::), then the variable name. Now we can assign some value.
Times of Execution: A static constructor will always execute once in the entire life cycle of a class. But a non-static constructor can execute zero time if no instance of the class is created and n times if the n instances are created.
Static classes cannot contain an instance constructor. However, they can contain a static constructor. Non-static classes should also define a static constructor if the class contains static members that require non-trivial initialization.
In a class template, when performing implicit instantiation, the members are instantiated on demand. Since the code does not use the static member, it is not even instantiated in the whole application.
When you do an explicit intantiation, the whole class and all of its members are instantiated, and that includes the static member variable, which is then initialized and you get your expected result.
Without the explicit instantiation you could do something like B* p = &Atempl<int>::b_;
(or any other use of the static member) to trigger the instantiation.
When a static member of a class template template is initialized is unspecified. In fact, unless you actuall use the static member, it should not be instantiated, and so never be initialized. If you explicitly instantiate the template, you force the instantiation of all of the members, which in turn forces the initialization (but I think exactly when it will be initialized is still unspecified).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With