0

I've been told that using global variables is a bad practice - and I am ready to agree with. I know already that you can write a function that returns a different value every time it's called in the following way:

unsigned int foo() {
   static unsigned int i = 0;
   return i++;
}

Is there a way to store some variable that is only readable/writable for, let's say, a couple of functions? For instance, let's say that I have an unordered_map<unsigned int, unsigned int> and I want some functions, to add / delete an element to / from it. Is that doable without using a global variable?

Jytug
  • 1,072
  • 2
  • 11
  • 29

3 Answers3

2

You can define these functions together in their own .cpp file and define the unordered_map<unsigned int, unsigned int> in an anonymous namespace inside the same .cpp file to make it only accessible to the functions you defined in that file.

Example cpp file:

namespace {
    std::unordered_map<unsigned int, unsigned int> private_map;
}

void map_add(unsigned int key, unsigned int value) {
    private_map.insert(std::pair<unsigned int, unsigned int>(key, value));
}

void map_delete(unsigned int key) {
    private_map.erase(key);
}

The header file to go with it:

#ifndef GlobalMap_H
#define GlobalMap_H

void map_add(unsigned int key, unsigned int value);
void map_delete(unsigned int key);

#endif

Including this header will allow you to call the functions that access the map, but you will not be able to access the map directly.

Jordan Melo
  • 1,193
  • 7
  • 26
1

It is not that global variables are bad. They are neither good nor bad, but as any tool, they are useful when are serving their purpose. Since this particular tool tends to be abused, there is a general notion 'global variables are bad, ooooggggh'. Still, there are global variables everywhere. For instance, std::cout is often a global variable.

However, certain scenarios demand global variables. But having read that 'they are bad' people start using something else - usually Singletons. Singletons are no better than global variables with the only exception of lazy iniatilization - but many singletons are not even using lazy initialization. As a result of this approach, every global variable is turned into Singleton (luckily it's already supported by many libraries, and turning global into singleton takes no more than several keystrokes) and the same abuse continues.

Instead of repeating 'global variables are bad' mantra, developers should understand what issues are associated with them, what are their benefits and choose a tool which suits the particular coding need.

Global variables make reasoning about the code hard. What it means is that since any function can write the value into it, it is hard to understand how the value changes over program execution. If, for instance, you realize that the value at some point is incorrect, you will have time figuring out how you ended up there. In worst case, you will have to grep the whole codebase for the name of this variable, which will be funny if codebase is 1000 of files, and name is something like i.

I will not tell you what to use in your case. There are already suggestions: make it a static variable of the class or make it local variable to the given .cpp file. Both are good, since they limit the scope of potential variable changers - to friends of class, or to functions defined in the same .cpp file. Taking class approach, you can have the functions and the data both static members of the class - this way you wan't need to define friends. Choice is yours.

SergeyA
  • 61,605
  • 5
  • 78
  • 137
  • Of course I'm aware that most of the statements of the form "something is bad" are not true, for there's appropriate use of everything (for instance http://stackoverflow.com/questions/245742/examples-of-good-gotos-in-c-or-c). I appreciate your answer though, because it might be useful for those in doubt – Jytug Nov 11 '15 at 16:37
0

Is there a way to store some variable that is only readable/writable for, let's say, a couple of functions?

You could make the variable a private and static data member of a class which declares the functions as friend.

#include <iostream>

class Foo
{
private:
   static unsigned int i;

   friend void f();
   friend void g();
   friend void h();
};

unsigned int Foo::i = 123;

void f() { std::cout << Foo::i; }
void g() { Foo::i = 456; }
void h() { std::cout << Foo::i; }

int main()
{
    f();
    g();
    h();
}

But I'd say that this is a rather unusual idiom.

Why not just turn the functions into member functions?

Christian Hackl
  • 27,051
  • 3
  • 32
  • 62