Getting rid of Globals.

Pages: 12
Hello,

I'm starting a new project and I wish to get rid of a few bad habits, one of which being global variables. I always end up having a number of global variables, because it "makes sense" (each and every function in the project needs those variables). Since I usually work with a single CPP file and dump the rest in headers, it hasn't been much of a problem yet. I have one header with all the global variable declarations, included by all other files. Now that I want to build and MFC interface around it, I'm forced to find some other solution.

Now, the easiest way would be using a struct to store all my global variables [and replace those few defines by consts]. However, since every function needs those parameteters, it seems ridiculous that there isn't a better way than passing the same struct to each and every function. I've seen people use the "extern" keyword, but I haven't been able to use it myself successfully.

Another note is that my project is very time-critical. I've heard that global variables are stored in (a) different memory (location) that provides faster access/use.

How should I go about this? Is there an easier/cleaner way than the struct? Is there a way to keep the efficiency gain without globals?
I'm not sure but I think you can declare them static? They will be global but their scope will only be within the single source file, if I'm not mistaken that is.

You can probably create a struct or class too, and use pass by reference when passing into functions. From what I remember when you pass a pointer to a function you're only passing the size of an integer instead of the whole size of struct or class. I'm not really sure if references ( & ) do it the same way though.

Edit:

Or why not just put the whole thing inside a class? your global variables become properties, then your functions become methods, make them static so you can just access them without creating any objects.
Last edited on
Static variables still belong to an object, don't they? Even if they're shared by all objects of the same class, it still requires an object to access them. It would solve the global-issue, but then I'd need to make a temporary object in each function. I'm not sure if that's preferably to passing a single object by reference to every function.
Last edited on
nope static variables belong to the class, in java they're called class variables. So you don't need to create an object to access them, you just need to do something like:

Classname::variable_name

If I remember correctly that is, I'm a bit rusty when it comes to C++ syntax.
That's pretty bad-ass. So can I simply initialize them without ever using an object?
yep, you can. I think that would help a lot making your code cleaner too. =)
Tested it and it is awesome. Thanks!

Any suggestion on reducing the amount of typing involved? Even with a short struct name, it gets a bit cumbersome. I thought of #defining shorter names (i.e. #define n parameters::n ), but that might be a bit messy, especially if I wish to use very short names (e.g. 'n') for the parameter variables.
hmm, I've never really tried reducing the amount of typing involved before. So I wouldn't really know how to do that sorry.

Edit:

I'm not sure but maybe the keyword using may help with that. Like if you remember

using namespace std;

There might be a way to use it with a single class? I'm not really sure though cause I've never tried it before. But there might be a possibility I mean.
Last edited on
Whenever you find that you have variables where it actually makes sense for them to be global, you need to start learning Object Oriented Programming.
You started the thread by saying you wanted to get rid of a bad habit -- that of using globals. Well, static members are also seen as bad. Not quite as bad as a fully fledged global, but you should not see them as good. They are just a global scoped by a class name. You should only use them sparingly, when you really, really have to!
Last edited on
@IceThatJaw: Thanks, but you're not actually helping me by saying that.

@andywestken: Any other alternatives are welcome too. I'm not too worried about bad practice in a software engineering view. I'm writing stand-alone projects that will only be used by myself; no-one else will run it or even see the code. My problem with globals is simply that I get into trouble if I want more than one .cpp file. All the other issues with globals don't really apply to my case.

Of course, if you can explain to me why statics are considered bad practice, I can judge for myself whether to use them or not.
From your comment about MFC. it does sound -- like IceThatJaw said -- that you need to switch to an o-o approach. That is the whole point of MFC verus raw WIN32

Globals and statics are considered bad because they are accessible by too many functions/objects. Ideally you want all data to be either passed as a parameter, stored as a temporary, or stored as a (non-static) class member. To tightly control how it can be changed.

(Note that static class constants are a different matter as no one can change them.)

I actually think that passing the struct to every function is a better (a better encapsulated, lower coupling) approach that the other solutions. But what you need to do is move forwards to o-o. If you have your C-style struct, then it's pretty easy to move it to a class with methods.

Then you don't have to pass the struct on from function to function. The member of the same class will have access to the same member data.

And it fits in with the MFC idiom, too.

Andy

Last edited on
I've been using the monostate pattern to manage global data

http://c2.com/cgi/wiki?MonostatePattern

The global data is declared static and private. You have an interface which which allows you to access this state. (can be in-line functions for time critical stuff)

The advantage of this structure is that you can reconfigure your global data (for better efficiency maybe), as long as the interface stays the same it won't ripple through into the code.

When you need to access the global data you just declare an instance of the monostate class. This should be pretty fast since there is no data initialisation required.

My monostate classes generally have some meaning, rather than just dumping all globals into one class.

If you are multithreading then you might have problems with this method.

I actually think that passing the struct to every function is a better (a better encapsulated, lower coupling) approach that the other solutions. But what you need to do is move forwards to o-o. If you have your C-style struct, then it's pretty easy to move it to a class with methods.

Then you don't have to pass the struct on from function to function. The member of the same class will have access to the same member data.


I am using an OO(-ish) structure. All the program logic is encapsulated in classes. The global variables are the read-in data and some parameters. The read-in data is needed everywhere, the parameters in specific functions of nearly every class. The problem with the first is frequency of use. Adding a class method call to each access of the data is extra work, both for the programmer [me] as the processor. For the parameters, I'd have to pass the object containing the parameters to every function, even if only one single function requires it, because the function call is deeply nested in other function calls.

I'd like to stress once again that the actual problems with Globals don't apply here. Nobody else will look at the code, let aside change it. I'm careful with my naming policy to make sure there will never be a local variable with the same name as a global. The only problem is that several cpp files will cause those global variables to be declared twice. If possible, I'd like to fix it in a "good practice" way, but if a dirty fix will do what I need, I'll gladly take it. Rather than just calling something "bad practice", I'd love to hear pro's and con's so I can make the decision myself [as well as learn something].

The class-with-statics is a possible solution to my problem: it's "safe" from multi-declaration, yet can be accessed everywhere without having to pass it to places that don't need it. "They can be accessed from too many places" is not a downside to me. It's a solo-project and I'm confident I can make sure I only access it in the correct places. If there are other downsides, feel free to mention them. I'm still trying to make an educated choice here, I'm just not going to accept a straight "bad practice" excuse without knowing why.
I still recommend the MonoState pattern solution.

A problem with global data (whether MonoState, Singleton of bare globals) is when you have multithreading. You need to ensure that only one thread at a time can access the global data.

If you have an interface between the raw globals and the program you stand a fighting chance of being able to control access to the globals. If you have bare globals sprinkled around then you do not. So you will never be able to multithread your application.
(OK, maybe if all the globals were constants and initialised before launching any threads)

Typing issues? Consider short access function names (one char) e.g.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class UniversalConstants
{
private:
  static double gravitationacceleration;
  ...
public:
  double g() const { return gravitationacceleration; }
  ...
};

// usage
void somefunc(...)
{
  UniversalConstants C; // need to access these
  ...
  F = m*C.g();
  ...
}


OK, so you have to type some brackets, but its not too bad.


Last edited on
i don't know if this was corrected, but a variable declared within a function that is static isn't global. you can only use it in that function but it retains its value upon exiting/reentering a function. also static is not exclusive to structs or classes. also global variables aren't a bad habit
@Gaminic

Rather than having to pass your globals to each function, it sounds like you only need to store a reference to your globals in each major component class object. Then all your member functions can access the 'globals' through that reference.

It is not uncommon to store variables in an external 'config' file. These configuration options are needed throughout the software. This sounds a bit like your scenario.

I wrote an IRC bot program recently that uses plugins. Each of the plugins needs to be able to read its configuration parameters from the config file. The way I managed this was to have a public member function in the main IRCBot class to retrieve a given value:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class IRCBot
{
private:
	std::map<std::string, std::string> config_map; // store config data
	
public:
	void init()
	{
		// read config data into config_map
	}

	/**
	 * Read a value from the config file according to a given key.
	 */
	std::string config(const std::string& key)
	{
		return config_map[key];
	}
};

Then each plugin is given a reference to the main IRCBot class when they are initialised. Then, when any of their functions requires a configuration setting, it simply asks the IRCBot object for the value:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class WonderPlugin
{
	IRCBot* bot;
	
public:
	void init(IRCBot* bot) { this->bot = bot; }
	
	void some_func()
	{
		// do some stuff
		
		std::string log_name = bot->config("log.file", "wonderplugin.log"); // grab global config info
		
		// do other stuff...
	}
};

Usually I find there is a suitable 'master' class (like IRCBot) that all the other classes need to be aware of and keep a reference to. If you are writing a GUI program, for instance, then you may have a main class that manages the creation of all the windows and dialogues. That class could then give a reference of itself to every object it instantiates and be the general controller/resource provider for the whole program.




Last edited on
That's oddly exactly what I thought of last night and I was going to post it here to ask if it's a valid way. Thanks for the suggestion; it's most likely what I'll be using. Just wondering: is there any difference between making your 'bot' variable a pointer or a reference?

@mik2718:
The monoState patterns seem a bit too complex for what I need. At this point, the "de-globalized" data class will contain nothing but read-only data (which doesn't care about multithreading, does it?). If I ever require (parts of) it to contain runtime-changeable data aswell, I'll revisit the monoState patterns again, but I must say that I don't really see the benefits of it [yet].

@Gaminic

Generally speaking I tend to avoid using references to bind dynamically created objects together because I feel that a pointer better describes the relationship. That being said this is one instance where a reference is probably appropriate and perhaps this is what I should have used in my project.

References need to be initialized in the constructor so as long as your satellite objects are created after and destroyed before the 'master' object to which they are all bound then I don't see any reason not to use one.

In fact references are probably a good way to convey the idea that the referred to object must always exist, and to help mandate that it does exist when the satellite object is created. It also sends a clear signal to the programmer not to delete it!
Already marked it as solved, but I ran into a bit of trouble:

I currently organized it as a class ("data") that contains some variables and the large matrix (2D array of ints). I store a reference to the data object in every class that needs it. However, for easy access, I want to keep a reference to the 2D array as well. However, I can't seem to find the proper syntax. Anyone who can help me?
Pages: 12