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.
Related
Suppose I have a c++ program which with several classes which are related like this:
class Application
{
public:
// some functions
private:
BusinessLogic businessLogic;
// some variables
};
class BusinessLogic
{
public:
// some functions
private:
BusinessLogicSubClass1 businessLogicSubClass1;
BusinessLogicSubClass2 businessLogicSubClass2;
// some other member variables
};
BusinessLogicSubClass1
{
public:
// some functions
private:
SubClassOfSubClass1 subClassOfSubClass1;
// some other member variables
};
// etc.... (you get the idea I hope)
The point is, I know at compile time that there is an Application class that contains the BusinessLogic class which contains many sub classes. I also know that I only need one instance of the Application class. Now the question is how to decide on where to store such a class in memory?
As far as I know there are three main possibilities:
on the stack:
int main()
{
Application application;
// do something with application
return 0;
}
on the heap:
int main()
{
std::unique_ptr application = std::make_unique<Application>();
// do something with application
return 0;
}
as a static:
int main()
{
static Application application;
// do something with application
return 0;
}
I read some information on the different types of memory. Based on what I read, I think it is not the best decision to store the application class on the stack. Mainly because the stack has a limited size and there is a very limited advantage of having the stack's automatic memory management (i.e. cleaning up variables that go out of scope) in this case.
I find it harder to decide however how to make the trade of between static and heap memory. In the simplified example above I think I go with static, because everything is known at compile time and static memory is said to be more efficient, compared to heap memory. (Does this way of thinking make any sense, or am I overlooking something here?)
However, there are some examples in which the choice becomes less evident. Suppose the application needs to be initialized via an .ini file. If you store the instance of the Application class on the heap, it will be possible to pass the initialization values via the constructor:
int main
{
IniFileReader reader;
InitializationValues iniValues = reader.GetIniValues();
std::unique_ptr application = std::make_unique<Application2>(iniValues);
// do something with application
return 0;
}
As far as I know, constructor initialization is considered to be better in terms of design than using some Init function like this:
int main
{
static Application3 application;
IniFileReader reader;
InitializationValues iniValues = reader.GetIniValues();
application.Init(iniValues);
// do something with application
return 0;
}
So here the choice is between cleaner code or a more efficient program. I realize this is sort of trade off is very much dependent on what type of application you intend to build.
What I am looking for is, if there are perhaps some rules of thumb or a sort of flow chart to decide where to store your classes?
Some (not necessarily good) examples of such rules could be:
if you know everything about a class at compile time and you know there is only one instance, try to always store it as a static.
always use the heap for objects that are shared between different threads.
it does not really matter in this or that case, so chose for cleaner code.
And secondly, are there any general guidelines or design principles on where to put the static classes? I find it hard to decide where to put a static class if they need to be accessed by more than one other class. Globals are generally considered bad design for instance.
A practical example of such a dilemma, can be found in the following article on the state design pattern: https://gameprogrammingpatterns.com/state.html --> see subsection static states
I am not sure if the authors choice to put a static instance of each state in the base class is the best design. He also admits to put them there "for no particular reason". Any suggestions for a better place? Make a sort of state-database class? Make a singleton of each state?
edit: changed mistake in code pointed out by Neil Butterworth
One very common way to handle your situation is to use a Singleton design pattern. you can find lots of good references on stack overflow, or via a simple google search. Take a look at this one for example. For you it would look something like this:
class Application
{
public:
static Application& getInstance()
{
static Application instance;
return instance;
}
private:
Application() {}
...
};
For dynamic parameters, I'm not sure I would agree that it's always better to initialize in the constructor, but the details really matter for this. There are cases where it does make sense, and cases where it doesn't. In the singleton case you almost always need some sort of separate "Init" call since you don't want to pass construction arguments on every call to getInstance().
To your question about "heap" versus "static". Assuming you really are only creating one Application instance, and you're running on a "desktop" OS like Linux/Window/MacOS, there will be no meaningful difference in runtime performance between these two. Uninitialized static variables are usually placed in .bss, and the first thing the OS will do when launching your process is dynamically allocate a bunch of pages to make space for the various data sections in your program. Not a whole lot different from what you're doing in code (i.e. a one-time dynamic memory allocation).
Recently a fellow worker showed to me a code like this:
void SomeClass::function()
{
static bool init = false;
if (!init)
{
// hundreds of lines of ugly code
}
init = true;
}
He wants to check if SomeClass is initialized in order to execute some piece of code once per Someclass instance but the fact is that only one instance of SomeClass will exist in all the lifetime of the program.
His question were about the init static variable, about when it's initialized. I've answered that the initialization occurs once, so the value will be false at first call and true the rest of its lifetime. After answering I've added that such use of static variables is bad practice but I haven't been able to explain why.
The reasons that I've been thinking so far are the following:
The behaviour of static bool init into SomeClass::function could be achieved with a non-static member variable.
Other functions in SomeClass couldn't check the static bool init value because it's visibility is limited to the void SomeClass::function() scope.
The static variables aren't OOPish because they define a global state instead of a object state.
This reasons looks poor, unclever and not very concrete to me so I'm asking for more reasons to explain why the use of static variables in function and member-function space are a bad practice.
Thanks!
This is certainly a rare occurrence, at least, in good quality code, because of the narrow case for which it's appropriate. What this basically does is a just-in-time initialization of a global state (to deliver some global functionality). A typical example of this is having a random number generator function that seeds the generator at the first call to it. Another typical use of this is a function that returns the instance of a singleton, initialized on the first call. But other use-case examples are few and far between.
In general terms, global state is not desirable, and having objects that contain self-sufficient states is preferred (for modularity, etc.). But if you need global state (and sometimes you do), you have to implement it somehow. If you need any kind of non-trivial global state, then you should probably go with a singleton class, and one of the preferred ways to deliver that application-wide single instance is through a function that delivers a reference to a local static instance initialized on the first call. If the global state needed is a bit more trivial, then doing the scheme with the local static bool flag is certainly an acceptable way to do it. In other words, I see no fundamental problem with employing that method, but I would naturally question its motivations (requiring a global state) if presented with such code.
As is always the case for global data, multi-threading will cause some problems with a simplistic implementation like this one. Naive introductions of global state are never going to be inherently thread-safe, and this case is no exception, you'd have to take measures to address that specific problem. And that is part of the reasons why global states are not desirable.
The behaviour of static bool init into SomeClass::function could be achieved with a non-static member variable.
If there is an alternative to achieve the same behavior, then the two alternatives have to be judged on the technical issues (like thread-safety). But in this case, the required behavior is the questionable thing, more so than the implementation details, and the existence of alternative implementations doesn't change that.
Second, I don't see how you can replace a just-in-time initialization of a global state by anything that is based on a non-static data member (a static data member, maybe). And even if you can, it would be wasteful (require per-object storage for a one-time-per-program-execution thing), and on that ground alone, wouldn't make it a better alternative.
Other functions in SomeClass couldn't check the static bool init value because it's visibility is limited to the void SomeClass::function() scope.
I would generally put that in the "Pro" column (as in Pro/Con). This is a good thing. This is information hiding or encapsulation. If you can hide away things that shouldn't be a concern to others, then great! But if there are other functions that would need to know that the global state has already been initialized or not, then you probably need something more along the lines of a singleton class.
The static variables aren't OOPish because they define a global state instead of a object state.
OOPish or not, who cares? But yes, the global state is the concern here. Not so much the use of a local static variable to implement its initialization. Global states, especially mutable global states, are bad in general and should never be abused. They hinder modularity (modules are less self-sufficient if they rely on global states), they introduce multi-threading concerns since they are inherently shared data, they make any function that use them non-reentrant (non-pure), they make debugging difficult, etc... the list goes on. But most of these issues are not tied to how you implement it. On the other hand, using a local static variable is a good way to solve the static-initialization-order-fiasco, so, they are good for that reason, one less problem to worry about when introducing a (well-justified) global state into your code.
Think multi-threading. This type of code is problematic when function() can be called concurrently by multiple threads. Without locking, you're open to race conditions; with locking, concurrency can suffer for no real gain.
Global state is probably the worst problem here. Other functions don't have to be concerned with it, so it's not an issue. The fact that it can be achieved without static variable essentially means you made some form of a singleton. Which of course introduces all problems that singleton has, like being totally unsuitable for multithreaded environment, for one.
Adding to what others said, you can't have multiple objects of this class at the same time, or at least would they not behave as expected. The first instance would set the static variable and do the initialization. The ones created later though would not have their own version of init but share it with all other instances. Since the first instance set it to true, all following won't do any initialization, which is most probably not what you want.
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.
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.
So the question is relatively straight forward, I have several semi-large lookup tables ~500kb a piece. Now these exact same tables are used by several class instantiations (maybe lots), with this in mind I don't want to store the same tables in each class. So I can either dump the entire tables onto the stack as 'static' members, or I can have 'static' pointers to these tables. In either case the constructor for the class will check whether they are initialized and do so if not. However, my question is, if I choose the static pointers to the tables (so as not to abuse the stack space) what is a good method for appropriately cleaning these up.
Also note that I have considered using boost::share_ptr, but opted not to, this is a very small project and I am not looking to add any dependencies.
Thanks
Static members will never be allocated on the stack. When you declare them (which of course, you do explicitly), they're assigned space somewhere (a data segment?).
If it makes sense that the lookup tables are members of the class, then make them static members!
When a class is instanced on the stack, the static member variables don't form part of the stack cost.
If, for instance, you want:
class MyClass {
...
static int LookUpTable[LARGENUM];
};
int MyClass:LookUpTable[LARGENUM];
When you instance MyClass on the stack, MyClass:LookUpTable points to the object that you've explicitly allocated on the last line of the codesample above. Best of all, there's no need to deallocate it, since it's essentially a global variable; it can't leak, since it's not on the heap.
If you don't free the memory for the tables at all, then when your program exits the OS will automatically throw away all memory allocated by your application. This is an appropriate strategy for handling memory that is allocated only once by your application.
Leaving the memory alone can actually improve performance too, because you won't waste time on shutdown trying to explicitly free everything and therefore possibly force a page in for all the memory you allocated. Just let the OS do it when you exit.
If these are lookup tables, the easiest solution is just to use std::vector:
class SomeClass {
/* ... */
static std::vector<element_type> static_data;
};
To initialize, you can do:
static_data.resize(numberOfElements);
// now initialize the contents
With this you can still do array-like access, as in:
SomeClass::static_data[42].foo();
And with any decent compiler, this should be as fast as a pointer to a native array.
Why don't you create a singleton class that manages the lookup tables? As it seems they need to be accessed by a number of classes; make the singleton the manager of the lookup tables accessible at global scope. Then all the classes can use the singleton getters/setters to manipulate the lookup tables. There are 3 advantages to this approach:-
If the static container size for the
lookup tables becomes large then the
default stack-size may ( 1MB on
Windows) lead to stack-overflow on
application statrt-up itself. Use a container that allocates dynamically.
If you plan to access the table via multiple-threads, the singleton class can be extended to accompany locked access.
You can also cleanup in the dtor of singleton during application exit.
I can think of several ways to approach for this depending upon what is trying to be accomplished.
If the data is static and fixed, using a static array which is global and initialized within the code would be a good approach. Everything is contained in the code and loaded when the program is started so it is available. Then all of the class which need access can access the information.
If the data is not static and needs to read in, an static STL structure, such as a vector, list or map would be good as it can grow as you add elements to the list. Some of these class provides lookup methods as well. Depending upon the data you are looking up, you may have to provide a structure and some operator to have the STL structures work correctly.
In either of the two case, you might what to make a static global class to read and contain the data. It can take care of managing initialization and access the data. You can use private members to indicate if the class has been read in and is available for use. If it has not, the class might be able to do the initialization by itself if it has enough information. The other class can call static function of the static global class to access the data. This provides encapsulation of the data, and then it can be used by several different classes without those classes needing to incorperate the large lookup table.
There are several possibilties with various advantages and disadvantages. I don't know what the table contains, so I'll call it an Entry.
If you just want the memory to be sure to go away when the program exits, use a global auto_ptr:
auto_ptr<Entry> pTable;
You can initialize it whenever you like, and it will automatically be deleted when the program exits. Unfortunately, it will pollute the global namespace.
It sounds like you are using the same table within multiple instances of the same class. In this case, it is usual to make it a static pointer of that class:
class MyClass {
...
protected:
static auto_ptr<Entry> pTable;
};
If you want it to be accessible in instances of different classes, then you might make it a static member of a function, these will also be deleted when the program exits, but the really nice thing is that it won't be initialized until the function is entered. I.e., the resource won't need to be allocated if the function is never called upon:
Entry* getTable() {
static auto_ptr<Entry> pTable = new Entry[ gNumEntries ];
return pTable;
}
You can do any of these with std::vector<Entry> rather than auto_ptr<Entry>, if you prefer, but the main advantage of that is that it can more easily be dynamically resized. That might not be something you value.