A friend of mine today asked me why should he prefer use of singleton over global static object?
The way I started it to explain was that the singleton can have state vs. static global object won't...but then I wasn't sure..because this in C++.. (I was coming from C#)
What are the advantages one over the other? (in C++)
Actually, in C++ preferred way is local static object.
Printer & thePrinter() {
static Printer printer;
return printer;
}
This is technically a singleton though, this function can even be a static method of a class. So it guaranties to be constructed before used unlike with global static objects, that can be created in any order, making it possible to fail unconsistently when one global object uses another, quite a common scenario.
What makes it better than common way of doing singletons with creating new instance by calling new is that object destructor will be called at the end of a program. It won't happen with dynamically allocated singleton.
Another positive side is there's no way to access singleton before it gets created, even from other static methods or from subclasses. Saves you some debugging time.
In C++, the order of instantiation of static objects in different compilation units is undefined. Thus it's possible for one global to reference another which is not constructed, blowing up your program. The singleton pattern removes this problem by tying construction to a static member function or free function.
There's a decent summary here.
A friend of mine today asked me why should he prefer use of singleton over global static object? The way I started it to explain was that the singleton can have state vs. static global object won't...but then I wasn't sure..because this in C++.. (I was coming from C#)
A static global object can have state in C# as well:
class myclass {
// can have state
// ...
public static myclass m = new myclass(); // globally accessible static instance, which can have state
}
What are the advantages one over the other? (in C++)
A singleton cripples your code, a global static instance does not.
There are countless questions on SO about the problems with singletons already. Here's one, and another, or another.
In short, a singleton gives you two things:
a globally accessible object, and
a guarantee that only one instance can be created.
If we want just the first point, we should create a globally accessible object.
And why would we ever want the second? We don't know in advance how our code may be used in the future, so why nail it down and remove what may be useful functionality? We're usually wrong when we predict that "I'll only need one instance". And there's a big difference between "I'll only need one instance" (correct answer is then to create one instance), and "the application can't under any circumstances run correctly if more than one instance is created. It will crash, format the user's harddrive and publish sensitive data on the internet" (the answer here is then: Most likely your app is broken, but if it isn't, then yes, a singleton is what you need)
Reason 1:
Singletons are easy to make so they are lazy build.
While you can do this with globals it take extra work by the developer. So by default globals are always initialized (apart from some special rules with namespaces).
So if your object is large and/or expensive to build you may not want to build it unless you really have to use it.
Reason 2:
Order of initialization (and destruction) problem.
GlobalRes& getGlobalRes()
{
static GlobalRes instance; // Lazily initialized.
return instance;
}
GlobalResTwo& getGlobalResTwo()
{
static GlobalResTwo instance; // Lazy again.
return instance;
}
// Order of destruction problem.
// The destructor of this object uses another global object so
// the order of destruction is important.
class GlobalResTwo
{
public:
GlobalResTwo()
{
getGlobalRes();
// At this point globalRes is fully initialized.
// Because it is fully initialized before this object it will be destroyed
// after this object is destroyed (Guaranteed)
}
~GlobalResTwo()
{
// It is safe to use globalRes because we know it will not be destroyed
// before this object.
getGlobalRes().doStuff();
}
};
Another benefit of the Singleton over the global static object is that because the constructor is private, there is a very clear, compiler enforced directive saying "There can only be one".
In comparison, with the global static object, there will be nothing stopping a developer writing code that creates an additional instance of this object.
The benefit of the extra constraint is that you have a guarantee as to how the object will be used.
Using Singleton("construct on first use") idiom, you can avoid static initialization order fiasco
In C++, there's not a huge amount of difference between the two in terms of actual usefulness. A global object can of course maintain its own state (possibly with other global variables, though I don't recommend it). If you're going to use a global or a singleton (and there are many reasons not to), the biggest reason to use a singleton over a global object is that with a singleton, you can have dynamic polymorphism by having several classes inheriting from a singleton base class.
OK, there are two reasons to go with a singleton really. One is the static order thing everyone's talking about.
The other is to prevent someone from doing something like this when using your code:
CoolThing blah;
gs_coolGlobalStaticThing = blah;
or, even worse:
gs_coolGlobalStaticThing = {};
The encapsulation aspect will protect your instance from idiots and malicious jerks.
Related
I am working on a C++ project having multiple classes that must be singletons, with dependencies between them (order of initialization matters).
I have come up with this solution:
All classes which I want to be singletons have protected constructors, e.g.:
class MySingleton1
{
protected:
MySingleton1();
}
Have a source file singleton_factory.cpp containing an instantiated class Singletons which derives from all classes which I want to be singletons, like this:
#include "MySingleton1.hpp"
#include "MySingleton2.hpp"
class Singletons : public MySingleton1, public MySingleton2 {}
static Singletons s_singletons;
Still in singleton_factory.cpp, for every singleton type, also implement a specialization of a getSingleton function:
template<>
MySingleton1& getSingleton()
{
return s_singletons;
}
template<>
MySingleton2& getSingleton()
{
return s_singletons;
}
The specializations of getSingleton will be "hid" under the generic templated variant, in singleton_factory.hpp:
template <class TSingleton>
TSingleton& getSingleton();
Advantages:
Low-coupling:
Singleton classes don't need to be "aware" of the Singletons class, the only need to hide their constructor under a protected qualifier (and that is not even mandatory, only good practice). The only code actually aware of the Singletons class is singleton_factory.cpp
Skinny dependencies for concrete instance: code that wants to use a singleton of type T only needs to include the header of type T and the skinny singleton_factory.hpp
Order of initialization can be controlled by changing the order of inheritance of the Singletons class
No lazy initialization => thread-safe?
getSingleton() is fast, no dynamic_cast, no reinterpret_cast
Disadvantages:
Every time a new singleton type appears, a getSingleton specialization, doing the same - i.e. "return s_singletons;" must be added to singleton_factory.cpp
So, as far as I can see, this is actually fairly good so I'm thinking to leave it like this, but I'm asking for your feedback (what better place to do that than the programming community?).
What extra advantages/disadvantages do you see with this solution?
What alternatives do you suggest?
This forces centralization of Singletons, which can mess up dependencies in more complex projects. The library that has singleton.cpp must depend on everything needed for every singleton. At the same time, anyone who uses a singleton must depend on the singleton.cpp library.
Basically your code could only work in a monolithic non-modular project. Scaling this to multiple dynamic libraries is next to impossible.
Your order of initialization must be maintained manually.
The static global variable's construction point is unsequenced with everything prior to the first expression in main.
A decent solution I've used is to create a dynamic library that holds the singleton memory.
To be a singleton, you inherit from a CRTP helper, which provides a ::Instance() inline method. People wanting the singleton use ::Instance().
::Instance() creates a static local variable lifetime token. It then attempts to get storage for the singleton from the primary DLL; if the object is already created, it simply casts the storage into the object type, and increases its reference count.
If not, it creates new storage and constructs the object in it.
At the destruction of the static local variable lifetime token, it reduces the reference count. If that reference count hits 0, it destroys it locally in the current dynamic library.
The lifetime of the singleton is now the union of the lifetime of the ::Instance() created variables. Destruction occurs in non-type-erased code, so we don't have to worry about the DLL with the code being unloaded. Storage is central. The DLL that stores the storage has to be lower level than every user of the Singleton system, but it in turn has no dependencies, so that isn't a pain.
This is far from perfect; singletons and lifetime are a constant problem, because clean program shutdown is hard and made harder by singleton's existence. But it has worked so far in a reasonably large project.
Can you use dependency injection in your case? i.e. have some serialized code create an instance of each class and pass a reference to the instance(s) into the constructors of any other instances that need access to them? This might simplify your design, if applicable. Ideally you could pass a separate, newly-created instance into each constructor to further reduce coupling but it seems you need to share state. In any case, perhaps it helps.
EDIT: Sorry my question was not clear, why do books/articles prefer implementation#1 over implementation#2?
What is the actual advantage of using pointer in implementation of Singleton class vs using a static object? Why do most books prefer this
class Singleton
{
private:
static Singleton *p_inst;
Singleton();
public:
static Singleton * instance()
{
if (!p_inst)
{
p_inst = new Singleton();
}
return p_inst;
}
};
over this
class Singleton
{
public:
static Singleton& Instance()
{
static Singleton inst;
return inst;
}
protected:
Singleton(); // Prevent construction
Singleton(const Singleton&); // Prevent construction by copying
Singleton& operator=(const Singleton&); // Prevent assignment
~Singleton(); // Prevent unwanted destruction
};
why do books/articles prefer implementation#1 over implementation#2?
Because most articles describing the Singleton anti-pattern don't fully understand all the hidden dangers when trying to implement it safely in C++. It's surprisingly difficult to get it right.
What is the actual advantage of using pointer in implementation of Singleton class vs using a static object?
Using a pointer, with new but no delete, ensures that the object will never be destroyed, so there is no danger of accessing it after its lifetime has ended. Combined with the "lazy" creation, the first time that it's accessed, this guarantees that all accesses are to a valid object. The disadvantages are that creation is not thread-safe, and that the object and any resources it acquires are not released at the end of the program.
Using a local static object, creation is thread-safe on any compiler that supports the C++11 threading model; also, the object will be destroyed at the end of the program. However, it is possible to access the object after its destruction (e.g. from the destructor of another static object), which could lead to nasty bugs.
The best option is to avoid static data, and globally-accessible data, as much as possible. In particular, never use the Singleton anti-pattern; it combines global, static data with weird instantiation restrictions that make testing unnecessarily difficult.
The second version (using a local static variable) has significant advantages.
It does not require use of the free-store, and so will not be detected as a memory leak. It is thread-safe (in C++11). It is shorter and simpler.
The only downsides are that it is impossible to make it portably threadsafe (for pre-C++11 compilers), and that it does not give you the option of explicitly destroying the singleton instance.
I'd always prefer the second, but the first does have a couple of potentially interesting advantages:-
Clarity - the checking of the pointer being null is effectively
what the compiler does under the hood when constructing static
objects. From a 'learning' perspective, it's instructive to
understand what's happening when you use static objects in method
scope.
Lazy Allocation - in the first case, the Singleton object is
heap-allocated. If your function never runs, the object is never
constructed and never consumes memory. But, in the second case,
memory is assigned by the linker to hold the object before the
program starts, even though 'construction' is lazy.
The second example is known by the name "Meyers' Singleton", because it was published first in either "Effective C++", or "More Effective C++". I'm not sure which one, but both were published after "Design Patterns" - so the Gang of Four might just as well have been unaware of the second pattern when their book was written.
Also, the first approach is much more standard for other languages - you can do the first one in Java or C#, but not the second, so people coming from different backgrounds could be another reason for the first one to be more famous.
On the technical side, with the first approach you can control when the singleton is destroyed, but this could also bring you a lot of headaches.
The second one has non-deterministic destruction. The first one, you are in control as to when you delete the pointer, if at all.
The first construct is not thread-safe, of course, but can be made so with boost::call_once (or std::call_once if available)
The second construct was common enough that many compilers made it thread-safe even if technically by the standard it isn't (although by the standard the object should only be created once, I'm not sure about the standard's view on completion of the construction before another thread uses it).
If there is no issue with the order of destruction then you can go ahead and use the static version, as long as your compiler guarantees it as thread-safe.
One advantage is that you do not have to check whether the singleton has already been instantiated.
Another is that you do not have to worry about de-allocating any memory.
How about a non-local static? Anyone see a problem with this?
class Singleton
{
static Singleton singleton;
Singleton();
// etc
public:
static Singleton &Instance() { return singleton; }
};
Singleton Singleton::singleton;
// etc
In C++, I use a singleton class and refer to the only instance in another class. I'm wondering what is the most efficient way to access this instance since it is a large data structure. I considered these things.
Getting a reference from the singleton class, other than passing the data structure by value
Using a global instance in my second class which uses the singleton class:
Singleton* singleInstance;
SingletonUser::SingletonUser ()
{
singleInstance = Singleton::getInstance(); //passes the single instance by reference, then it will be used in the class wherever needed
}
Doing the same thing inside a function of the second class so that I get a reference to the singleton class's instance when I want it (Need to access it several times in several functions).
I'm not sure which practice is the best one. Can someone explain, and if there is a more efficient way, explain that too?
Thanks!
If you're passing your singleton instance by value, then it's not really a singleton, is it?
Simply return a reference (or a pointer) to the instance whenever you need to access it (#1). Caching the reference once for each client is only going to add complexity and almost certainly won't be any faster.
I'm not sure what the difference is between #1 and #3, besides added complexity. Both use a function to access the singleton instance via a reference/pointer.
Firstly in C++ avoid pointers when possible, instead pass by reference:
Singleton& Singleton::getInstance() {
return *singleton;
}
Then in the code:
Singleton& st = Singleton::getInstance();
st.someFunction();
Your option #3 is most preferable. Try to not cache references unnecessarily - those cached references tend to be a maintenance burden as time goes on.
And just in general, try avoid the singleton pattern. In C++, a global function (non-member) is just as good and allows the design to evolve.
Currently I'm using singleton pattern for certain global objects in my application (Qt application for Symbian environment). However, because of some problems (C++ checking singleton pointers) it looks like that I have to change the logic.
I have 3 classes (logger, settings and container for some temp data) that I need to access via multiple different objects. Currently they are all created using singleton pattern. The logger basically is just one public method Log() with some internal logic when the settings and container have multiple get/set methods with some additional logic (e.g. QFileSystemWatcher). In addition, logger and settings have some cross-reference (e.g. logger needs some settings and settings logs errors).
Currently everything is "working fine", but there is still some problems that should be taken care of and it seems like they are not easy to implement for the singletons (possible memory leaks/null pointers). Now I have two different ways to handle this:
Create global objects (e.g. extern Logger log;) and initialize them on application startup.
Create objects in my main object and pass them to the children as a reference.
How I have few questions related to these:
Case 1.
Is it better to use stack or heap?
I'm going to declare those objects in some globals.h header using extern keyword. Is it ok?
I think in this case I have to remove that 2-way reference (settings needs logger and vice versa.)?
Case 2.
Should the objects be created in stack or heap in my main object (e.g. Logger *log = new Logger() vs Logger log;)
Long reference chains do not look nice (e.g. if i have to pass the object over multiple childrens).
What about in children?
If I pass a pointer to the children like this (I don't want to copy it, just use the "reference"): Children(Logger *log) : m_Log(log) what happens when the children is deleted? Should I set the local pointer m_Log to NULL or?
If I use stack I'll send reference to the child (Children(Logger &log) : m_Log(log)) where m_Log is a reference variable (Logger& m_Log;) right?
What should I note in terms of Qt memory management in this case?
Case 3.
Continue with singleton and initialize singleton objects during the startup (that would solve the null pointers). Then the only problem would possible memory leaks. My implementation follows this example. Is there a possible memory leak when I'm accessing the class using. What about singleton destruction?
#define LOG Logger::Instance()->Log
Thanks for reading.
Summary in simple terms:
if you use global objects, prefer the singleton pattern as a lesser evil. Note that a singleton should have global access! Dan-O's solution is not really a singleton pattern and it defeats the power of singletons even though he suggests it's no different.
if you use global objects, use lazy construction to avoid initialization order problems (initialize them when they are first accessed).
if you use singletons, instead of making everything that needs to be globally acccessible a singleton, consider making one singleton (Application) which stores the other globally-accessible objects (Logger, Settings, etc.) but don't make these objects singletons.
if you use locals, consider #3 anyway to avoid having to pass so many things around your system.
[Edit] I made a mistake and misplaced the static in safe_static which Dan pointed out. Thanks to him for that. I was blind for a moment and didn't realize the mistake based on the questions he was asking which lead to a most awkward situation. I tried to explain the lazy construction (aka lazy loading) behavior of singletons and he did not follow that I made a mistake and I still didn't realize I made one until the next day. I'm not interested in argument, only providing the best advice, but I must suggest strongly against some of the advice, particularly this case:
#include "log.h"
// declare your logger class here in the cpp file:
class Logger
{
// ... your impl as a singleton
}
void Log( const char* data )
{
Logger.getInstance().DoRealLog( data );
}
If you are going to go with globally accessible objects like singletons, then at least avoid this! It may have appealing syntax for the client, but it goes against a lot of the issues that singletons try to mitigate. You want a publicly accessible singleton instance and if you create a Log function like this, you want to pass your singleton instance to it. There are many reasons for this, but here is just one scenario: you might want to create separate Logger singletons with a common interface (error logger vs. warning logger vs. user message logger, e.g.). This method does not allow the client to choose and make use of a common logging interface. It also forces the singleton instance to be retrieved each time you log something, which makes it so that if you ever decide to steer away from singletons, there will be that much more code to rewrite.
Create global objects (e.g. extern
Logger log;) and initialize them on
application startup.
Try to avoid this at all costs for user-defined types, at least. Giving the object external linkage means that your logger will be constructed prior to the main entry point, and if it depends on any other global data like it, there's no guarantee about initialization order (your Logger could be accessing uninitialized objects).
Instead, consider this approach where access is initialization:
Logger& safe_static()
{
static Logger logger;
return logger;
}
Or in your case:
// Logger::instance is a static method
Logger& Logger::instance()
{
static Logger logger;
return logger;
}
In this function, the logger will not be created until the safe_static method is called. If you apply this to all similar data, you don't have to worry about initialization order since initialization order will follow the access pattern.
Note that despite its name, it isn't uber safe. This is still prone to thread-related problems if two threads concurrently call safe_static for the first time at the same time. One way to avoid this is to call these methods at the beginning of your application so that the data is guaranteed to be initialized post startup.
Create objects in my main object and
pass them to the children as a
reference.
It might become cumbersome and increase code size significantly to pass multiple objects around this way. Consider consolidating those objects into a single aggregate which has all the contextual data necessary.
Is it better to use stack or heap?
From a general standpoint, if your data is small and can fit comfortably in the stack, the stack is generally preferable. Stack allocation/deallocation is super fast (just incrementing/decrementing a stack register) and doesn't have any problems with thread contention.
However, since you are asking this specifically with respect to global objects, the stack doesn't make much sense. Perhaps you're asking whether you should use the heap or the data segment. The latter is fine for many cases and doesn't suffer from memory leak problems.
I'm going to declare those objects in
some globals.h header using extern
keyword. Is it ok?
No. #see safe_static above.
I think in this case I have to remove that 2-way reference (settings
needs logger and vice versa.)?
It's always good to try to eliminate circular dependencies from your code, but if you can't, #see safe_static.
If I pass a pointer to the children
like this (I don't want to copy it,
just use the "reference"):
Children(Logger *log) : m_Log(log)
what happens when the children is
deleted? Should I set the local
pointer m_Log to NULL or?
There's no need to do this. I'm assuming the memory management for the logger is not dealt with in the child. If you want a more robust solution, you can use boost::shared_ptr and reference counting to manage the logger's lifetime.
If I use stack I'll send reference to
the child (Children(Logger &log) :
m_Log(log)) where m_Log is a reference
variable (Logger& m_Log;) right?
You can pass by reference regardless of whether you use the stack or heap. However, storing pointers as members over references has the benefit that the compiler can generate a meaningful assignment operator (if applicable) in cases where it's desired but you don't need to explicitly define one yourself.
Case 3. Continue with singleton and
initialize singleton objects during
the startup (that would solve the null
pointers). Then the only problem would
possible memory leaks. My
implementation follows this example.
Is there a possible memory leak when
I'm accessing the class using. What
about singleton destruction?
Use boost::scoped_ptr or just store your classes as static objects inside an accessor function, like in safe_static above.
I found the other answer to be a little misleading. Here is mine, hopefully the SO community will determine which answer is better:
Is it better to use the stack or the heap?
Assuming by "the stack" you meant as a global (and thus in the data segment), don't worry about it, do whichever is easier for you. Remember that if you allocate it on the heap you do have to call delete.
I'm going to declare those objects in some globals.h header using extern keyword. Is it ok?
Why do you need to do that? The only classes that need access to the globals are the singletons themselves. The globals can even be static local variables, ala:
class c_Foo
{
static c_Foo& Instance()
{
static c_Foo g_foo; // static local variable will live for full life of the program, but cannot be accessed elsewhere, forcing others to use cFoo::Instance()
return g_foo;
}
};
If you don't want to use the static local then a private static member variable of type c_Foo (in my example) would be more appropriate than a straight global.
Remember, you want the lifetime of the class to be "global" (ie not destroyed until application exit), not the instance itself.
I think in this case I have to remove that 2-way reference (settings needs logger and vice versa.)?
All of the externed globals would have to be forward declared, but as I said above you don't need this header file.
Should the objects be created in stack or heap in my main object (e.g. Logger *log = new Logger() vs Logger log;)
I can't really answer this, don't worry about it again.
Long reference chains do not look nice
(e.g. if i have to pass the object
over multiple childrens).
What about in children?
Great points, you have realized that this would be a huge pain in the butt. In the case of something like a logger it would be hellish to pass references to every module just so they could spit out logging info. More appropriate would be a single static "Log" function ala C, if your logger has useful state then make it a singleton that is only visible to your log function. You can declare and implement your entire logger class in the same .cpp file that you implement your log function in. Then nothing else will be aware of this special functionality.
Here is what I mean:
file: log.h
#ifndef LOG_H
#define LOG_H
void Log( const char* data ); // or QString or whatever you're passing to your logger
#endif//LOG_H
file: log.cpp
#include "log.h"
// declare your logger class here in the cpp file:
class Logger
{
// ... your impl as a singleton
}
void Log( const char* data )
{
Logger.getInstance().DoRealLog( data );
}
This is a fine logger interface, all the power of your singleton, limited fuss.
Is there a possible memory leak when I'm accessing the class using. What about singleton destruction?
There is a risk of double instantiation if you're lazily allocating the singleton on the heap in a multithreaded environment. This would cause surplus instances to leak.
There are somewhat similar risks if you use a static local: Link
In my opinion explicit construction when execution starts is the best option, but whether it is done in the data segment (with a static variable in a class or global variable) or the heap is very unlikely to matter in your case. If you do allocate it on the heap you should also delete it.
Let's consider a C++ class. At the beginning of the execution I want to read a set of values from an XML file and assign them to 7 of the data members of this class. Those values do not change during the whole execution and they have to be shared by all the objects / instances of the class in question. Are static data members the most elegant way to achieve this behavior? (Of course, I do not consider global variables)
As others have mentioned, the use of static members in this case seems appropriate. Just remember that it is not foolproof; some of the issues with global data apply to static members:
You cannot control the order of initialization of your static members, so you need to make sure that no globals or other statics refer to these objects. See this C++ FAQ Question for more details and also for some tips for avoiding this problem.
If your accessing these in a multi-threaded environment you need to make sure that the members are fully initialized before you spawn any threads.
Sounds like a good use of static variables to me. You're using these more as fixed parameters than variables, and the values legitimately need to be shared.
static members would work here and are perfectly acceptable. Another option is to use a singleton pattern for the class that holds these members to ensure that they are constructed/set only once.
It is not a clean design. Static class members are global state and global state is bad.
It might not cause you trouble if this is a small- to medium-sized project and you do not have high goals for automatic testing, but since you ask: there are better ways.
A cleaner design would be to create a Factory for the class and have the Factory pass your seven variables to the class when it constructs it. It is then the Factory's responsility to ensure that all instances share the same values.
That way your class becomes testable and you have properly separated your concerns.
PS. Don't use singletons either.
sounds like an appropriate use of static class members. just don't forget that they're really global variables with a namespace and (maybe) some protection. therefore, if there's the possibility that your application could someday evolve separate 'environments' or something that would need a set of these globals for each, you'd have painted yourself into a corner.
as suggested by Rob, consider using a singleton, which is easier to turn later into some kind of managed environment variable.
At the beginning of the execution I want to read a set of values from an
XML file and assign them to 7 of the
data members of this class. Those
values do not change during the whole
execution and they have to be shared
by all the objects / instances of the
class in question.
The sentence in boldface is the kicker here. As long as that statement holds, the use of static variables is OK. How will this be enforced?
It's hard to. So, if for your use right now the statement is always true, go ahead. If you want to be same from some future developer (or you) using your classes wrong (like reading another XML file midway in the program), then do something like what Rasmus Farber says.
Yes, static datamembers are what you look for. But you have to take care for the initialization/destruction order of your static variables. There is no mechanism in C++ to ensure that your static variables are initialized before you use them across translation units. To be safe, use what looks like the singleton pattern and is well known to fix that issue. It works because:
All static objects are completely constructed after the complete construction of any xml_stuff instance.
The order of destruction of static objects in C++ is the exact opposite of the completion of their construction (when their constructor finishes execution).
Code:
class xml_stuff {
public:
xml_stuff() {
// 1. touch all members once
// => 2. they are created before used
// => 3. they are created before the first xml_stuff instance
// => 4. they will be destructed after the last xml_stuff instance is
// destructed at program exit.
get_member1();
get_member2();
get_member3();
// ...
}
// the first time their respective function is called, these
// objects will be created and references to them are returned.
static type1 & get_member1() { static type1 t; return t; }
static type2 & get_member2() { static type2 t; return t; }
static type1 & get_member3() { static type1 t; return t; }
// ... all other 7 members
};
Now, the objects returned by xml_stuff::get_memberN() are valid the whole lifetime of any xml_stuff instance, because any of those members were constructed before any xml_stuff instance. Using plain static data members, you cannot ensure that, because order of creation across translation units is left undefined in C++.
As long as you think of testability and you have another way to set the static variables besides reading in a file, plus you don't rely on the data benig unchanged for the entire execution time of the process - you should be fine.
I've found that thinking of writing tests when you design your code helps you keep the code well-factored and reusable.