Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Static variable resetting its value to 0 on it's own apparently

Tags:

c++

static

I have a base class called Component which has a number of classes derived from it. I want each class to have an integer associated with it (doesn't matter which component gets what value, as long as they start at 0 and are contiguous). I don't know how to do this directly, so in the same file as Component I added the following:

template <typename T>
class ComponentIdentifier
{
public:
    static unsigned int cid;
};

static unsigned int CIDCounter = 0;
template <typename T> unsigned int ComponentIdentifier<T> = CIDCounter++;

template <typename T> unsigned int ComponentID()
{
    return ComponentIdentifier<T>::cid;
}

unsigned int ComponentCount(); // Defined in .cpp file, just returns CIDCounter

Now I tested the ComponentID() function and it appears to work fine. Each component class that I tried ComponentID on returned a different integer just as I expected. However, whenever I call ComponentCount I get 0.

e.g. if I have the following lines of code:

std::cout << ComponentID<AAA>() << std::endl;
std::cout << ComponentID<BBB>() << std::endl;
std::cout << ComponentID<CCC>() << std::endl;
std::cout << ComponentCount() << std::endl;

then my output is:

0
1
2
0

I suspect what's happening is that CIDCounter is being set to 0 again after its used to set the cid's of each component, but I don't know for sure and that seems kind of weird. Is there a way to do what I want or am I crazy and this whole plan doomed to failure?

like image 297
Alex Avatar asked Jan 20 '23 22:01

Alex


1 Answers

You've declared your identifier as static:

static unsigned int CIDCounter = 0;

which means each compilation unit will get its own copy of the variable. Instead you should declare it as extern in the header file:

extern unsigned int CIDCounter;

and initialise it in the implementation file

unsigned int CIDCounter = 0;

One should note that without appropriate locks this won't be thread-safe.

To clarify further:

The static keyword in this context means that the variable or function is limited to the current compilation unit (usually a cpp file). I'm guessing you have, say, a main.cpp and an idcounter.cpp - so now we have two variables (one for each of the compilation units) main_CIDCounter and idcounter_CIDCounter (variable names are for explanation only!).

When you execute your test code in main.cpp the template function sees main_CIDCounter because that's the current compilation unit and you get the expected 1,2,3. However, when you call ComponentCount() code from idcounter.cpp is used, and that code sees idcounter_CIDCounter - which hasn't been modified at all. If you had other compilation units you would see similar behaviour, where each cpp file would appear to be maintaining its own ID counter.

The fix I've described is simply to only have one copy of CIDCounter in idcounter.cpp, and declare it as external in all the other compilation units.

like image 127
Adam Bowen Avatar answered Jan 31 '23 11:01

Adam Bowen