Sasha
Sasha

Reputation:

What is the best way to declare a global variable?

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

Answers (8)

Johannes Schaub - litb
Johannes Schaub - litb

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

Stack Overflow is garbage
Stack Overflow is garbage

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

Adam Rosenfield
Adam Rosenfield

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

Daniel Earwicker
Daniel Earwicker

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

Naveen
Naveen

Reputation: 73503

Why not use good old singleton pattern?

Upvotes: -1

dirkgently
dirkgently

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

Nemanja Trifunovic
Nemanja Trifunovic

Reputation: 24559

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

Upvotes: 4

SingleNegationElimination
SingleNegationElimination

Reputation: 156308

extern MyGlobalClass MyGlobalClassInstance;

Edit: Not static >.<

Upvotes: 0

Related Questions