C++: When (and how) are C++ Global Static Constructors Called?

后端 未结 5 1052
借酒劲吻你
借酒劲吻你 2020-11-29 03:13

I\'m working on some C++ code and I\'ve run into a question which has been nagging me for a while... Assuming I\'m compiling with GCC on a Linux host for an ELF target, wher

5条回答
  •  北海茫月
    2020-11-29 03:22

    The grantees you have:

    • All static non-local objects in the global namespace are constructed before main()
    • All static non-local objects in another namespace are constructed before any functions/methods in that namespace are used (Thus allowing the compiler to potentially lazy evaluate them [but don't count on this behavior]).
    • All static non-local objects in a translation unit are constructed in the order of declaration.
    • Nothing is defined about the order between translation units.
    • All static non-local objects are destroyed in the reverse order of creation. (This includes the static function variables (which are lazily created on first use).

    If you have globals that have dependencies on each other you have two options:

    • Put them in the same translation unit.
    • Transform them into static function variables retrieved and constructed on first use.

    Example 1: Global A's constructor uses Global log

    class AType
    {    AType()  { log.report("A Constructed");}};
    
    LogType    log;
    AType      A;
    
    // Or 
    Class AType() 
    {    AType()  { getLog().report("A Constructed");}};
    LogType& getLog()
    {
        static LogType  log;
        return log;
    }
    // Define A anywhere;
    

    Example Global B's destructor uses Global log

    Here you have to grantee that the object log is not destroyed before the object B. This means that log must be fully constructed before B (as the reverse order of destruction rule will then apply). Again the same techniques can be used. Either put them in the same translation unit or use a function to get log.

    class BType
    {    ~BType()  { log.report("B Destroyed");}};
    
    LogType    log;
    BType      B;   // B constructed after log (so B will be destroyed first)
    
    // Or 
    Class BType() 
    {    BType()    { getLog();}
         /*
          * If log is used in the destructor then it must not be destroyed before B
          * This means it must be constructed before B 
          * (reverse order destruction guarantees that it will then be destroyed after B)
          *
          * To achieve this just call the getLog() function in the constructor.
          * This means that 'log' will be fully constructed before this object.
          * This means it will be destroyed after and thus safe to use in the destructor.
          */
        ~BType()    { getLog().report("B Destroyed");}
    };
    LogType& getLog()
    {
        static LogType  log;
        return log;
    }
    // Define B anywhere;
    

提交回复
热议问题