Just got back into C++ a couple months ago. Mainly, my plan is to get into game development. Hard field to get into, I know, but through school and a hopeful internship this summer, I will be able to fight my way in. I am currently learning SDL and I think I am ready to start developing my first game. Just to get a feel of it and learn how to effectively layout my classes, I am doing a simple game, probably just Black Jack. Anyway, my questions that have to do with C++. Sorry if these are stupid questions; I have been learning on my own which is sometimes hard.

I know it is bad coding to have global variables for the most part, but how exactly do you replace them? I have many different variables that are called by a bunch of different classes and functions, like the screen width, height, and bpp. Someone recommended using singleton classes. I really don't know what singleton classes are. After doing a bunch of research, I think it means to have a class with private static variables and functions with the class calling it's own constructor, or something like that... I also ran into people saying singleton classes are just as dangerous as global variables and are not a good replacement. Can someone please clear these up for me?

Recommended Answers

All 11 Replies

I would have to say that using global variables should not be used. IMHO all variables should either be in a function like main or in a class. It looks cleaner and is better understood if you pass a variable to a function instead of making it global and just using it in a function.

[EDIT]
I have never used a singleton class but it kinda seems like cheating to me.
[/EDIT]

The convention is pointers, or references.

//Passing a variable via a reference!

#include <iostream>
using namespace std;
void swap(int & x, int & y);
int main()
{
int x = 1;
int y = 6;

cout << "\nBefore Swap, in Main: " << x <<" "<< y << "\n";
swap(x,y);
cout << "\nAfter Swap, in Main: " << x <<" "<< y << "\n";
return 0;
}

void swap (int & x, int & y)
{
cout << "\nBefore swap, in swap: " << x <<" "<< y << "\n";
int temp;
temp = x;
x = y;
y = temp;
cout << "After swap, in swap: " << x <<" "<< y;
}
//Passing a variable via a pointer!

#include <iostream>
using namespace std;
void swap(int * x, int * y);
int main()
{
int x = 1;
int y = 6;

cout << "\nBefore Swap, in Main: " << x <<" "<< y << "\n";
swap(&x,&y);
cout << "\nAfter Swap, in Main: " << x <<" "<< y << "\n";
return 0;
}

void swap (int * x, int * y)
{
cout << "\nBefore swap, in swap: " << *x <<" "<< *y << "\n";
int temp;
temp = *x;
*x = *y;
*y = temp;
cout << "After swap, in swap: " << *x <<" "<< *y;
}

They both accomplish the exact same thing, that is, they both edit a local variable globally. This is because the function accesses the memory address of the local variable, as opposed to simply the value of the local variable.

Forget about Singleton, its an antipattern. For you case, go with a more object oriented approach and define the variables in a class or namespace with appropriate context. For example :

class Window{
public:
 static const int SCREEN_WIDTH = 100;
  //...
};

or maybe :

namespace Environment{
  namespace PhysicsConstants{
      const float PI = 3.14f;
      const float GRAVITY = 9.18;
      ///...
  }
};

and as suggested, you can also just pass around the variable when needed via appropriate parameter list.

Global data is bad, however it is not always avoidable. There are no hard and fast rules in C++ just best practice and less good practice and you need to know when to ignore best practice.

I would say make a big effort to avoid making any global variables that are not a pod type (pointers, char, integers, floats, bools) i.e. no global data with a type of class or struct (noting that structs and class are more or less the same).

I say this because if you do then those variables get constructed before main is running and destructed after main exits and you end up with code running at times when you can not really be sure of the state of the system. And if you have more than one defined in different files you have no control over the order the construction takes place in.

Singletons do have there uses but remember the purpose of a singleton is not to replace global data but to provide a class that guarantees that the entire program uses the same instance of it while still providing the object orientated advantages of encapsulation, hierarchy and polymorphism.

However I implement them with a static pointer to the type rather than a static copy of the type. A pointer is a pod and causes no problems with code running outside main, then you first time the singleton is accessed you simple construct it (or if you prefer have a separate function to construct that is called in main).

I find singletons particularly useful when combined with the fly-weight pattern which in turn I often use while implementing the state pattern.

I am not intending to tell what is good and what is bad. Sometimes using Singletons can simplify the code a lot. Think about this, in a game we probably want to have a bunch of classes which have manager purposes. For example: TextureManager, ShaderManager, EventManager, StringManager, SoundManager, Application and so on. These are classes which you probably want to have access in every part of your code. Again, using Singletons is a way (not THE way) to do that. Avoid using Singleton when You can, use them only if You really need. About Globals, I preffer logically packing them in a Namespace or as static fields in Struct (or Class) to which they belong.

Simple Singleton examples:

class Singleton
{
    static Singleton* instance;
    Singleton(){};   // Hidden contructor
  public:
    static Singleton* const GetInstance();
};

Singleton* Singleton::instance = NULL;

Singleton* const Singleton::GetInstance()
{
	if(instance == NULL)
	{
		instance = new Singleton();
	}
	return instance;
}

Although this is a very simple example, it show the purpose of the Singleton class. To avoid writing the same code again and again (for every manager class), I use templates, other write macros. I can`t really say which approach is better.

I hope this post will help you (or anyone else).

Thanks everyone for your replies.

Singletons do have there uses but remember the purpose of a singleton is not to replace global data but to provide a class that guarantees that the entire program uses the same instance of it while still providing the object orientated advantages of encapsulation, hierarchy and polymorphism.

That was exactly what I was looking for. Now I think I understand the reason behind Singletons. Let me see if I can come up with the example I will be using in my first game.

Let's say I have a GameSystem class. This class initializes SDL and will hold the constants such as screen width, height, bpp and fps. I only want this class to be called 1 time, but the whole program will need to access some of it's variables, through a function or otherwise. Is this a good way to do it? Would it be best for this class to be a singleton?

Of course, there would be other managers, such as sound and image and whatever.

@OP: Trust me on this. Using singleton is rarely justified, I mean rarely. Just create only create a single object from the class. For your example, see the previous post using static variables, and such.

Member Avatar for JSPMA1988

Instead of globals or singletons, there is always the use of pointers. That way the variables can be defined once in your main function and you just pass the pointers around to your other functions as needed. This saves on memory allocation and usage, saves processing time by not having to assign, call, and destroy local function variables, and has a myriad of other advantages. There are of course disadvantages, such as (with pointers) direct memory access and potential unintentional address modification that could result in a fatal error.

I personally use pointers and references since I find using them slightly easier and more efficient than creating temporary variables in my functions...but that's just me.

This is a huge design issue. I will try my best to keep it brief. I will go from worse to best options, in my humble opinion (from experience in making a few simple computer games and having incrementally implemented a better solution each time).

Global variables are horrible.. even POD-types. Try to avoid them at all costs. They are a very very last resort. Philosophically, the motivation is that in OOP, you want objects to encapsulate the state of the application. This way you implement each class such that they maintain a valid and working state (except in error-states, where they should be duly reported or logged). If you have global variables, your application has a state that is independent of its objects and it becomes a nightmare to keep it stable because now all classes have to be implemented to preserve some ill-defined application state. Now, global _constants_ are much different. If you need a bunch of values like some physical constants (e.g. gravity or Plank's constant) or mathematical constants (e.g. Pi or e), they don't define the state of the application since they don't change, so you can safely use global constants to store those values (but make sure they are POD though). To avoid name-clashing, split them up into their most suited namespaces.

Singletons are not nice and should be avoided. But for some purposes, they are really the only solution. As for the implementation, there have been a few prior posts with suggestions, but I (and many others) would recommend this one. The reason why singletons are not nice is because they can always be replaced by passing around a pointer or reference to that "global" object that is sort-of needed by everything else in the software. In other words, instead of forcing only a single instance of the class to exist, you just create one (in main or some other root class) and pass a reference to it to all parts of the application that needs the values it stores. The motivation for using a singleton is if you need to pass this "global" object to every object in your application, and there is no reason why you would ever want to have more than one instance of this "global" class. If this is the situation you are stuck in, then a singleton is probably what you need. However, in OOP, the idea that every object (or a significant subset of them) require the use of some external "global" object to function means that their functionality is highly coupled to that of this "global" object, and this is exactly what you want to avoid in OOP. In OOP, you want every class to be as fully self-sufficient as possible. This is for mainly two reasons: 1) what if you make a change to this "global" class? In the worst case, you will have to revisit your implementation of all the classes that depend on it. Moreover, this will put a lot of stress on you to make sure you have a completely final version of this "global" class before you implement too much of the application, and this is very difficult to do (i.e. anticipate all the aspects of all the functionality of all your application before you even start to code anything). 2) what if you make another application or project in the future and you want to reuse the classes you had implemented, but on a different framework? Since your classes depend on the framework they were designed for, they are not easily portable (which is not nice when you are starting to make a simple computer game.. what about the next simple computer game you might work on.. and the next after that.. wouldn't it be nicer if you could reuse most of the stuff from your previous project to kick-start the next?).

If you are going to need a singleton for some problem, make sure that the problem is neither avoidable nor too blurry (ill-defined or not well circumscribed). Do not implement a singleton and use it as some sort of bag in which you toss all the stuff that you would like or think you would like to access from everywhere in the application (this is basically no different than using global variables). This is not a case of "oh, I have to use a singleton for problem X, so, since I have one now (and have "broken" the rule), mind as well use it for Y and Z". If you think that all the parts of your software will need to know the screen specs (width, height, bpp, etc.) and you cannot not avoid that, implement a singleton that encapsulates this information. If later you find that some other information needs to be global, implement another singleton for that specific purpose. This will limit the interdependency damage caused to your application.

The third option, as mentioned before, is to pass the reference down the chain of objects that makes up your application. In this case, a typical implementation would look like this:

class root {
  public:
    //some "global" information here
    //...
};

class Foo {
  protected:
    const root& rootObj;
  public:
    Foo(const root& aRootObj) : rootObj(aRootObj) { };
    virtual ~Foo() { };
    //now methods can be implemented to use "rootObj".
};

int main() {
  root myRoot;
  Foo myFoo(myRoot);
};

Now, this has some obvious drawbacks. First, it adds to memory consumption because all your objects have their own reference (or pointer). This obviously can become a problem if many objects (and even small objects) require to hold this reference. It is also very annoying to create object with the reference to root all the time. Second, there is an implicit assumption that the root object will exist throughout the lifetime of the Foo object (if root is deleted, the reference will become invalid and you will get a segmentation fault or access violation). Most of the time this is not a huge concern since usually you can make it so that all the objects that hold a reference to the root object are also _owned_ by the root object and thus, will be deleted just before the root object gets deleted. The use of weak_ptr/shared_ptr can solve this problem with a small additional overhead. Now, the nice thing about this implementation is that you can also distinguish objects which will change the root object (non-const reference) and those that won't (const reference) (with a singleton, all you can do is to make the singleton read-only to all (making the access function return a non-const reference), read-write to all (making the access function return a const reference), or either to anyone (providing both access functions).. all very vaguely defined and undesirable in terms of OOP design principles).

Another option is to pass-by-reference the root object to all the methods that need it when they are called. For example:

class screen {
  public:
    int width, height;
    //...
};

class scene {
  public:
    void render(screen& aScreen);
};

This avoids the memory overhead, but of course it adds an additional parameter to the function calls. If there aren't that many functions that really need this "global" object, this is usually the way to go. It has all the advantages of the previous method and none of its main disadvantages.

The ultimate, ideal solution is to rethink your design such that your objects don't need to use any "global" information, they are fully self-contained. This is very hard, especially in game programming, and I haven't seen many game engine implementation that really achieve that mostly because of the nature of 3D rendering that requires using shaders, textures, meshes, and other resources altogether to work. I find that using policy classes and template meta-programming in general is quite useful to avoid the coupling. Basically, policy classes allow you to sort-of construct a class whose dependencies on another parts of the application are encapsulated in its underlying policy classes, so each piece of the class is independent in its own right even though the composite class has all these "unavoidable" interdependencies. This can also be achieved to some extent with dynamic polymorphism (and often with multiple inheritance), but I find it nicer with generic programming techniques.

Ok.. well, I wasn't able to keep it brief, as usual... Hope it helps!

commented: Excellent +6
commented: Great post +1

Brief is not always better. Thanks for the very detailed reply! After reading this and a certain book, I think I understand Singletons now. When it comes to this type of game, avoid it, because it is really easy and better to avoid it. I got thrown off trail a little bit by another want-to-be game developer that used singletons for all her base classes. I now realize that it is bad practice. Thanks everyone for the replies.

Other people have mentioned creating a single instance of the class and passing it to everything else.

I can honestly say that I can not see anyone where I work viewing that as a good idea. I work on one of our smaller projects and it has ~560 cpp files and ~750 h files and since classes are defined approximately 1 to a header file (say about 700 classes) I can't see passing an object by reference into all of them as being a good idea. If you are multi-threading then that also complicates the process of passing a single (or worst more than 1) pointer round everywhere.

Of those 700 classes I would guess may be 4 - 5 are singletons, each one with a very well defined purpose.

An example that appears in many of our projects is an error (or event) logger to allow logging and printing of messages about program state to the screen (if there is one) and also file (if there is a filing system) and other locations (over the network for example). You are going to want to be able to output status messages from anywhere and a class nicely encapsulates the code and data required to do this.

It is this kind of service that is not really a part of the job that the program does but that is a service required by all parts of the program that I would consider a singleton for.

What I am trying to emphasize is that there are no hard and fast rules. We can say avoid global data and some would clearly say avoid singletons we are not saying you will manage to go through your whole programming life without using them.

Using terms of the C++ FAQ global data is evil (and singletons depending on who you listen to).

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.