Global variables in modern C++

2020-03-25 05:25发布

问题:

What are the (objective) disadvantages of creating a class where all members (attributes, functions) are static? In particular in comparison with the use of a namespace? Or would you rather create global variables/functions?

I like creating static attributes because I find them "tidier." (I know exactly where they come from, etc.) I'm not very familiar with namespaces. And I'm not comfortable at all with global variables, because I'm not very familiar with C keywords such as extern and static.

Further, if we consider the class

class MyStaticClass
{
    private:

        static int x;
        static double y;

    public:

        static float s;
        static double weatherForecast(unsigned int, char);
};

and the namespace

namespace MyNamespace
{
    int x;
    double y;
    float s;
    double weatherForecast(unsigned int, char);
}
  1. Are there differences (performance-wise) between calling MyStaticClass::weatherForecast and calling MyNamespace::weatherForecast?

  2. Are there differences (performance-wise) between reading/writing MyStaticClass::s and reading/writing MyNamespace::s?

  3. Would any of the answers to the above questions change if classes were used instead of primary types?

回答1:

Is it "good practice" to create a class where all members (attributes, functions) are static?

This is called "monostate" and it depends.

Or would you rather create a namespace?

A class with static functions can be a template argument, whereas a namespace cannot. On the other hand, namespaces allow for argument-dependent lookup, whereas classes - less so.

Or would you rather create global variables/functions?

Some things are truly global, like the standard streams, Logger objects, event loop engines (thread-specific global). For example, code that passes Logger objects in each and every call or stores them as member variables is more complicated than necessary, IMO.

There is an often cited misconception that the order of dynamic initialization accross translation units is undefined, so people overuse Singletons instead of plain globals to make sure the Singleton object is initialized before its first use. However, there is a portable technique called Schwarz Counter that is used for initializing the standard streams (std::cout and friends), which makes sure that these globals are initialized before their first use even before main is entered.


Answers to your updated questions: no, no, no.