C++ Nifty Counter idiom; why?

后端 未结 4 540

I recently came across the Nifty Counter Idiom. My understanding is that this is used to implement globals in the standard library like cout, cerr, etc. Since the experts have c

4条回答
  •  鱼传尺愫
    2021-01-31 09:44

    Summarizing the answers and comments:

    Let's compare 3 different options for a library, wishing to present a global Singleton, as a variable or via a getter function:

    Option 1 - the nifty counter pattern, allowing the use of a global variable that is:

    • assured to be created once
    • assured to be created before the first usage
    • assured to be created once across all shared objects that are dynamically linked with the library creating this global variable.

    Option 2 - the Meyers singleton pattern with a reference variable (as presented in the question):

    • assured to be created once
    • assured to be created before the first usage

    However, it will create a copy of the singleton object in shared objects, even if all shared objects and the main are linked dynamically with the library. This is because the Singleton reference variable is declared static in a header file and must have its initialization ready at compile time wherever it is used, including in shared objects, during compile time, before meeting the program they will be loaded to.


    Option 3 - the Meyers singleton pattern without a reference variable (calling a getter for retrieving the Singleton object):

    • assured to be created once
    • assured to be created before the first usage
    • assured to be created once across all shared objects that are dynamically linked with the library creating this Singleton.

    However, in this option there is no global variable nor inline call, each call for retrieving the Singleton is a function call (that can be cached on the caller side).

    This option would look like:

    // libA .h
    struct A {
        A();
    };
    
    A& getA();
    
    // some other header
    A global_a2 = getA();
    
    // main
    int main() {
        std::cerr << "main\n";
    }
    
    // libA .cpp - need to be dynamically linked! (same as libstdc++ is...)
    // thus the below shall be created only once in the process
    A& getA() {
        static A a;
        return a;
    } 
    
    A::A() { std::cerr << "construct A\n"; }
    

提交回复
热议问题