In C++11 what makes this thread safe is the following from the draft C++11 standard section 6.7 Declaration statement which says (emphasis mine):
The zero-initialization (8.5) of all block-scope variables with static
  storage duration (3.7.1) or thread storage duration (3.7.2) is
  performed before any other initialization takes place. [...] Otherwise
  such a variable is initialized the first time control passes through
  its declaration; such a variable is considered initialized upon the
  completion of its initialization. If the initialization exits by
  throwing an exception, the initialization is not complete, so it will
  be tried again the next time control enters the declaration. If
  control enters the declaration concurrently while the variable is
  being initialized, the concurrent execution shall wait for completion
  of the initialization. [...]
while pre C++11 section 6.7 says:
[...]Otherwise such an object is initialized the first time control passes
  through its declaration; such an object is considered initialized upon
  the completion of its initialization. If the initialization exits by
  throwing an exception, the initialization is not complete, so it will
  be tried again the next time control enters the declaration.[...]
which does not have the same guarantee that C++11 has and so it would seem pre C++11 it is not specified and therefore you can not count on it. Although this does not prevent implementations from making stronger guarantees. 
This make sense since pre C++11 the memory model did not including threading.