Difference between revisions of "Global variables"

From vegard.wiki
Jump to navigation Jump to search
(add note)
(clarify)
 
Line 51: Line 51:
 
but here, the argument may not be a temporary expression.
 
but here, the argument may not be a temporary expression.
  
Also note that any such globals declared in the parameter list must be declared after all the other parameters, since they are default-initialized to the global!
+
Note that any such globals declared in the parameter list must be declared after all the other parameters, since they are (local) references default-initialized as pointing to the global variable!
  
 
[[Category:Programming]]
 
[[Category:Programming]]
 
[[Category:C++]]
 
[[Category:C++]]

Latest revision as of 10:34, 10 February 2020

Global variables are discouraged by a lot of people for various different reasons [1]. One objection is that it becomes harder to reason about (and test) functions because they have a "hidden" input (i.e. the global state).

I think global variables have their place, and are honestly not that different from, say, instance variables used by methods. One way to simply make it clear that global state is used in the code would be to provide a couple of wrappers for defining and declaring the use of global variables, respectively:

Definition:

#define DEFINE_GLOBAL(type, name) __thread typeof(type) global_##name
#define USE_GLOBAL(name) typeof(global_##name) &name = global_##name

Usage:

#include <cstdio>

DEFINE_GLOBAL(int, x);

void foo()
{
    USE_GLOBAL(x);

    printf("x = %d\n", x);
}

#if 0 // doesn't work, since x is undeclared
void bar()
{
    printf("x = %d\n", x);
}
#endif

// complex type declarations also work:
DEFINE_GLOBAL(void (*)(int), fn);

If you want to be able to override the global for a function (e.g. for testing using mock data, without actually modifying the global), one could even put the declaration in the parameter list:

void baz(USE_GLOBAL(x))
{
    printf("x = %d\n", x);
}

This function can be called either as

baz()

in which case it will use the actual global variable, or

int value = 12;
baz(value);

but here, the argument may not be a temporary expression.

Note that any such globals declared in the parameter list must be declared after all the other parameters, since they are (local) references default-initialized as pointing to the global variable!