Reputation:
In C++, say you want to declare a global variable to be used by many. How do you do it?
I commonly use declare and define in cpp file, and then use extern in other cpp file (and not headers).
I don't like this approach, and I am considering something along these lines:
In a header file:
some_file.h
Class MYGlobalClass
{
};
MyGlobalClass& MyGlobalClassInstance()
{
static MYGlobalClass instance;
return instance;
}
Edit
Consider in the following contexts:
What are your thoughts, suggestions, new ideas?
Upvotes: 5
Views: 6352
Reputation: 507413
Declare it in one header file (using extern
), and define it in one .cpp
(or whatever other extension) file. You may use a function and return a reference to a static variable like you showed to circumvent problems with construction order relative to other such namespace scope variables in other .cpp
files. But remember that won't protect you from destruction order problems - which is in the exact reverse order from construction (these things are called "static initialization order fiasco". If you use a function like yours and put it into headers, make it inline to make the redefinition of the function valid when it is included into multiple .cpp
files (logically, the function is still only apparent once, because the static in it will only exist once, not separately for each file it is included into). Alternatively just declare it in a header but define it in one .cpp
file (but then, remove the inline from it!).
inline A& getA() { static A a; return a; }
The potential problems with destruction order can be circumvented by using new
:
inline A& getA() { static A *a = new A; return *a; }
The destructor of it, however, will never be called then. If you need thread safety, you should add a mutex that protects against multiple accesses. boost.thread
probably has something for that.
Upvotes: 2
Reputation: 248289
The best advice is probably "try to avoid globals". People don't need global variables as often as they think. Usually it turns out that "passing everything as arguments to constructors" isn't quite as much work as people think when they hear the suggestion. It also tends to lead to cleaner code with fewer, and more explicit, dependencies.
I'm not aware of any "correct" way to declare globals in C++. The way you do it now works fine, but the order of initialization is unspecified, so if there are any dependencies between your globals, you're in trouble.
A function returning a static instance more or less solves that problem, but isn't thread safe.
And a singleton is just a terrible idea. It doesn't solve your problem, but adds additional constraints to your code, which weren't actually necessary, and will most likely come back and bite you later.
Upvotes: 10
Reputation: 400692
It it's truly a global variable that could theoretically be accessed externally by any module, you should put the extern declaration in the header file:
// MyClass.h
class MyClass { ... };
extern MyClass myGlobalInstance;
// MyClass.cpp
MyClass myGlobalInstance;
If it's just a global object that should really only be accessed by a single module, limit its scope by either making it a private (or protected) static class variable, a static function variable (if it's only needed by one function), or in an anonymous namespace:
Option 1:
// MyClass.h
class MyClass
{
private: // or protected, if you want it accessible by subclasses
static MyClass myGlobalInstance;
};
Option 2:
// MyClass.cpp
void someFunction()
{
// it's global, but only accessible inside this function
static MyClass myGlobalInstance;
...
}
Option 3:
// MyClass.cpp
namespace
{
MyClass myGlobalInstance;
}
// it's now only accessible in this file
Upvotes: 1
Reputation: 116764
Your idea of a static inside the accessor function is significantly different from a global variable. The difference is when it is constructed, and is most likely to be a major problem with multiple threads. What if two threads call MyGlobalClassInstance
at the same time? Depending on the environment, but I suspect this is typical of most C++ compilers, you will potentially get two calls to the constructor of MyGlobalClass
running at the same time, addressing the same area of memory.
If you're single-threaded, it's less likely to be a problem.
If you declare the instance as a normal static member or as a normal global variable in the source file, you'll probably have an easier time, because the constructor will be called before main
executes, before you have a chance to start other threads.
Upvotes: 2
Reputation: 111336
declare and define in cpp file
Keep the extern
-ed declaration in a header. Define it only once in an implementation file.
You are close. Use a namespace instead for global variables.
namespace myns {
int foo = 0;
}
Now, if it is a class object, you are looking at the Singletion pattern. In fact, your sample code reflects a Singleton design. However, if you are going to define the function in the header, make it inline -- ODR violation otherwise.
Upvotes: 1
Reputation: 24559
Declare as extern in one header file included by "many" and define it in one *.cpp file
Upvotes: 4
Reputation: 156308
extern MyGlobalClass MyGlobalClassInstance;
Edit: Not static >.<
Upvotes: 0