2

What are disadvantages of using static variables like in following code:

namespace XXX
{
    static int i;
    class YYY
    {
        static m_i;     
    };
}

Is using static variables only in .cpp (so they are invisible to other code) file OK?

fspirit
  • 2,537
  • 2
  • 19
  • 27

5 Answers5

3

It totally depends on what you need to do. There is no general aversion to using statics. Note that statics are essentially the singleton pattern, so all the pros/cons about singletons apply.

In terms of threads you have to pay attention since the same instance could be access by multiple threads at the same time. If you only need to read the data then you shouldn't have any problems. If you need to modify the data you have to worry about synchronization.

For code reuse and testing singeltons can often pose a problem. You can't for example recreate the object in a test, or have multiple run in parallel. In general when I use singletons/statics I try to ensure that one instance of the entire life of all tests, parallel executions, etc. is totally okay.

Invisible statics as you call them (visible only to the compilation unit) are a good idea. This helps you maintain synchronization between threads and manage them correctly. If they have global visibility then they can be modified at any time (well private variables can't, so they are also good).


Also note that atomic variables can be safely read/written from various threads. For simple counters this is often a good solution: using atomic increment. In C++0x you can use "atomic", previously use your OS/compiler function that does it. As with the singleton pattern, you can easily design classes where each function is synchronized so the singleton user doesn't have to worry about it. That is to say, statics aren't inherently thread-safe even when doing writing.

edA-qa mort-ora-y
  • 30,295
  • 39
  • 137
  • 267
  • "If you only need to read the data then you shouldn't have any problems"... in general, you can't read data safely while another thread's updating it. Whether the programmer always feels that every "an/other thread" is theirs in the sense of ownership "you" implies is doubtful. Even for `int`, you can miss updates if you don't use something to sync caches.... – Tony Delroy Apr 28 '11 at 07:24
  • @Tony, I said **only** need to **read**. Of course you can't write to it without synchronization. But that's what I said in the sentence after...? – edA-qa mort-ora-y Apr 28 '11 at 07:45
  • It's the "you" that's the problem... from a programmer's perspective "you" means he/she reading, and they may not think about whether other threads they didn't personally write are updating. It's ambiguous. – Tony Delroy Apr 28 '11 at 07:49
  • That's just picking at the nuances of the English language. In the context of a team project *you* should always be interpreted as the plural form. It is also very clear that my advice is generic and not targeted at this particular individual. I refuse to write "you guys" or use the passive tense when "you" is totally acceptable. – edA-qa mort-ora-y Apr 28 '11 at 07:56
2

Various things allowed by C++ represent choices and compromises in software design. There is nothing inherently, absolutely evil about any of them (except perhaps throw specifications, which Prof. Stroustrop deems a broken facility ;-P).

Whether this particular code is a good choice in a particular situation depends on many factors. For example:

  • there'll only be one copy shared by the entire program
    • may be ideal, e.g. you want to have some program-wide modal state
    • terrible: code setting/using the value may find other code has modified it meanwhile (this gets increasingly likely as the program gets larger and more complex)
    • terrible: in multi-threaded code you must use locking and/or atomic operations to avoid data corruption and consequent erroneous behaviour and/or crashes
  • being static:
    • other translation units won't have access to it
    • it won't pollute the symbol table exposed by a good IDE etc.

In short, if you realise that namespaces and static just reduce identifier clashes, they've got all the other pros/cons associated with global variables....

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
1

Also you can have some problems with static class members while working with runtime shared libs. For example: if you have:

class A {
//...
static int staticInt;
//...
}; 

And you link this class to main executable AND to runtime shared lib, which is used by this executable (via dlopen) in several cases you can receive segmentation faults due to reinitialization of main executable's copy of static member by loaded shared lib. You can find more details concerning this issue here and there

Community
  • 1
  • 1
beduin
  • 7,943
  • 3
  • 27
  • 24
0

For one it's not thread safe. You might want to consider the singleton pattern with some kind of locking to protect it.

Robert S. Barnes
  • 39,711
  • 30
  • 131
  • 179
0

One disadvantage you must be aware of is the so-called "static initialization order fiasco." Here is an example:

// foo.cpp

class foo {
  public:
    static bar m_bar;
};

bar foo::m_bar;

// baz.cpp

class baz {
  public:
    baz() { 
     /* some code */
     foo::m_bar.someMethod(); 
    }
};

baz g_baz; //TROUBLE!!

The C++ standard makes no guarantee about which will be initialized first of m_bar and g_baz. If you're lucky and m_bar gets initialized first, g_baz will be constructed without a hitch. If not, your program will likely segfault, or worse.

Replacing m_bar with a method returning a static pointer constructed on first use circumvents this problem (NB: it's still not thread-safe):

class foo {
  public:
    static bar &getBar() { if(!m_barinst) m_barinst = new bar; return *m_barinst; }
  private:
    static bar *m_barinst;
};

bar *foo::m_barinst = NULL;
user168715
  • 5,469
  • 1
  • 31
  • 42