【问题标题】:Calling a function immediately before main在 main 之前立即调用函数
【发布时间】:2011-07-10 11:17:29
【问题描述】:

是否可以在输入main 之前立即注册一个要运行的函数?我知道所有全局对象都是在输入main 之前创建的,所以我可以将代码放在全局对象的构造函数中,但这并不能保证任何特定的顺序。我想做的是将一些注册代码放入构造函数中,但是唉,我不知道该放什么:) 我猜这是高度系统特定的?

【问题讨论】:

  • 您能否将“在输入main 之前立即运行”的代码放入main(),然后创建从那里调用的第二个函数the_real_main()?也许那是作弊。
  • 声明:不保证任何特定的顺序总体上是一般性的,因此并不完全正确。编译单元的构造顺序很好地定义为声明顺序。只是编译单元之间的顺序没有很好地定义(因为它取决于链接器)。
  • 你到底想用这个函数来完成什么,而这个函数不能作为main中调用的第一个函数来完成?

标签: c++ function callback main


【解决方案1】:

如果您使用gcc,则可以在函数上使用constructor 属性,使其在main 之前调用(有关详细信息,请参阅documentation)。

constructor

destructor

constructor 属性使函数在执行进入main () 之前被自动调用。同样,destructor 属性会导致函数在main () 完成或exit () 被调用后自动调用。具有这些属性的函数对于初始化将在程序执行期间隐式使用的数据很有用。

【讨论】:

    【解决方案2】:

    不确定这是否正是您想要的......但它应该可以完成这项工作。

    int main() {
      static int foo = registerSomething();
    }
    

    最好在 main 或首次访问时显式调用此类注册函数(但如果您是多线程的,则首次访问 init 可能会造成问题)。

    【讨论】:

    • 这与只使用registerSomething() 没有静态变量没有太大区别。
    • 不,但可以说它(带有一些强制)在 main 中的代码之前逻辑执行 :)
    【解决方案3】:

    我在这里猜测但是:

    1. 你想在不同的编译单元中注册一些东西
    2. 您在注册时遇到了问题,因为您保存注册的全局变量尚未构建。

    C++ 定义函数静态在它第一次被访问之前被初始化,所以你可以通过下面显示的方式来解决它。

    typedef std::map<std::string, std::string> RegistrationCache;
    
    RegistrationCache& get_string_map()
    {
        static RegistrationCache cache;
        return cache;
    }
    
    class Registration
    {
        Registration(std::string name, std::string value)
        {
            get_string_map()[name] = value;
        }
    };
    

    【讨论】:

      【解决方案4】:

      目标

      假设您想要以下内容:

      STATIC_EXECUTE {
        printf("This probably prints first"\n");
      }
      
      STATIC_EXECUTE {
        printf("But order isn't guaranteed in the language spec, IIRC"\n");
      }
      
      int main(int argc, char **argv) {
        printf("This definitely prints last. Buh Bye.\n");
      }
      

      实施

      C++ 版本 - 静态变量 + 构造函数:

      // This is some crazy magic that produces __StaticExecute__247
      // Vanilla interpolation of __StaticExecute__##__LINE__ would produce __StaticExecute____LINE__
      // I still can't figure out why it works, but it has to do with macro resolution ordering
      // If you already have Boost, you can omit this part
      #define BOOST_PP_CAT(a, b) BOOST_PP_CAT_I(a, b)
      #define BOOST_PP_CAT_I(a, b) BOOST_PP_CAT_II(~, a ## b)
      #define BOOST_PP_CAT_II(p, res) res
      
      // This avoids repeating the BOOST_PP_CAT 5X
      #define STATIC_EXECUTE \
        STATIC_EXECUTE_I(BOOST_PP_CAT(__StaticExecute__, __LINE__))
      
      // This is the meat, a static instance of a class whose constructor runs your code
      #define STATIC_EXECUTE_I(uniq_name)               \
      static struct uniq_name {                         \
        uniq_name();                                    \
      } BOOST_PP_CAT(uniq_name, __var);                 \
      uniq_name::uniq_name()  // followed by { ... }
      

      C 版本 - 静态变量 + 函数

      // ... 
      
      // The meat: a static variable initialized from a function call
      #define STATIC_EXECUTE_I(uniq_name)            \
      static void uniq_name ();                      \
      static int BOOST_PP_CAT(uniq_name, __var) =    \
        (uniq_name(), 0);                            \
      static void uniq_name()                        // followed by { ... }
      

      注释

      • 恕我直言,C++ 版本稍微优雅一些​​。理论上,它消耗的空间略少。否则,土豆,po-tat-哦。

      • 警告:我没有在正确的纯 C 编译器上测试“C”版本。手指交叉;如果它不起作用,请发布注释。

      • 警告:编译器的可移植性通常是一件棘手的事情。如果其他编译器存在错误,我不会感到震惊。

      • BOOST_PP_CAT 代码从boost/preprocessor/cat.hpp 被盗。我简化了实现,在此过程中可能损害了可移植性。如果它不起作用,请尝试原始(更详细的)实现,并在下面发表评论。或者,如果您已经在使用 Boost,则可以使用他们的版本。

      • 如果您想了解 Boost 的魔力,请注意(至少对我而言,并且在这种情况下),以下内容似乎也有效:

          #define BOOST_PP_CAT(a, b) BOOST_PP_CAT_I(a, b)
          #define BOOST_PP_CAT_I(a, b) a ## b

      【讨论】:

      • 哎呀。我的第一次尝试失败了。 StaticExecute__##__LINE 变成 StaticExecute____LINE,而不是像我预期的那样变成 __StaticExecute__247。用一些从 Boost 偷来的疯狂魔法修复它。
      猜你喜欢
      • 1970-01-01
      • 2017-08-26
      • 1970-01-01
      • 2012-06-09
      • 1970-01-01
      • 2014-09-18
      • 2011-06-20
      • 1970-01-01
      • 2010-09-16
      相关资源
      最近更新 更多