views:

699

answers:

8

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:

  • can be used in multi-threaded applications
  • namespace pollution
  • may NOT necessery be a singleton, as many instances of this might be created

What are your thoughts, suggestions, new ideas?

A: 

extern MyGlobalClass MyGlobalClassInstance;

Edit: Not static >.<

TokenMacGuy
static will not work, I need to share it accross files, modules, or even libraries. thanks for your time though
+4  A: 

Declare as extern in one header file included by "many" and define it in one *.cpp file

Nemanja Trifunovic
Good idea! perhaps define an inline function in header file? and include the header by many?
No school like the old school.
chaos
A: 

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.

dirkgently
I have considered namespace....
You are thinking of a Singleton object. In that case have an accessor and use it. Of course, you still need to include the header. Take a look.http://en.wikipedia.org/wiki/Singleton_pattern
dirkgently
Thank you, I'm familiar with Singleton. However, it is NOT the solution I am looking for.
A: 

Why not use good old singleton pattern?

Naveen
Because it only adds new problems, and doesn't solve the one he needs solved
jalf
I don't want just one instance of that class! plus a needless overhead
But the code you have written is a singleton with exactly one static instance!!
aJ
No it isn't. There's nothing to stop Sasha from instantiating multiple MYGlobalClass instances. A singleton would make that impossible. A singleton *guarantees* that precisely one instance will exist.
jalf
+2  A: 

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.

Daniel Earwicker
On the other hand, if you declare a plain global variable, you get all the problems with unpredictable initialization order.
jalf
Yep. Ain't C++ a bitch?! :)
Daniel Earwicker
yep :) (10 chars padding)
jalf
suggest a correction to unpredictable order initialization...
Assuming that you don't need to be calling it all the time and therefore can afford the overhead, why not just add a scoped lock in the beginning of MyGlobalClassInstance ?
Pukku
@Sasha: That was terrible. But I laughed anyway.
e.James
+1  A: 

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
Adam Rosenfield
+9  A: 

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.

jalf
+2  A: 

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.

Johannes Schaub - litb
what is the problems with destruction order?
yesraaj
it's the exact reverse order of construction. i.e if an object is created before you called getA() the first time, then it will be destroyed after the object in getA(). I.e there is a particular order. If you for example access getA() in the objects destructor, you will access a dangling reference.
Johannes Schaub - litb
search for "static initialization order fiasco" and i think you will find quite a few explanation (longer than my short overview here, of course) of that weirdness.
Johannes Schaub - litb
note that "constructed" means that the constructor finished. so if B does B() { getA(); } in its ctor then the A object in getA() is constructed *before* B (because its ctor finishes first), and you can safely do ~B() { getA(). .. } in B's destructor.
Johannes Schaub - litb
its too late to sleep, I will learn and post any further update here
yesraaj
Thanks Litb Following links is helpful in understanding the problem http://www.parashift.com/c++-faq-lite/ctors.html
yesraaj