【问题标题】:How to force the initialization of a static local variable before main?如何在main之前强制初始化静态局部变量?
【发布时间】:2016-06-09 16:27:35
【问题描述】:

考虑下面的一对函数:

double MYAPI foo(double x) { 
     return x; 
}
Register register_foo_([] { 
     return reg(&foo, "foo", ...); // function name repeated used
});

register_foo_ 是一个全局变量,在dllmain 之前初始化,其构造函数采用一个 lambda,该 lambda 从字面上重复引用它上面的函数名称。如果注册码可以在上面的函数中移动以减少出错的机会,那就太好了。我试过了:

double MYAPI foo(double x) { 
     static Register register_foo_([] { 
          return reg(&foo, "foo", ...); // static local does not initialize before dllmain
     });
     return x; 
}

如果上面的代码有效,那么我可以轻松地将其转换为使用__FUNCNAME__ 的宏。有没有办法在dllmain之前强制初始化静态局部变量register_foo_

【问题讨论】:

  • 如果调用foo没有不良副作用,可以在dllmain开头调用
  • 所以基本上你想在main之前调用一个函数?还是我弄糊涂了?
  • @Praetorian 这试图实现的是自动跟踪注册的功能。所以调用 dllmain 不起作用,因为我需要明确地写出函数名称。
  • @Galik 是的,我想在 dllmain 之前自动初始化一些东西。

标签: c++ c++11


【解决方案1】:

函数(方法)的局部静态变量在首次使用它们所在的函数时被初始化。(它们在程序加载时被初始化为零,然后在首次输入函数时通过代码“正确”初始化。 ) 请参阅answers to this question。因此,您提议将该代码移动到函数中会改变初始化的语义,并且它不会起作用。

您的原始代码有效,因此您显然想要将代码移动到函数内,以便在您的脑海中以某种方式更紧密地联系在一起 - 或者代码读者的脑海中 - 这样您就可以看到您的字符串常量名和函数名是对的。也可能这样您就可以确保注册已完成。因此,您想要的是完成 DRY。

传统的(也是唯一的)方法是使用扩展为注册调用和函数头的预处理器宏。

您建议自己使用宏 - 现在扩展宏,这样它不仅会生成注册函数,而且生成函数头。

【讨论】:

  • 有没有办法让我想要的工作?从概念上讲,函数名列表是一个编译时间常数。
  • @CandyChiu - 扩展我的答案以回答您的问题。
  • 谢谢。我赞成你的解释,但选择了昆汀的答案,因为他发布了代码。
【解决方案2】:

我想你想实现类似的语法:

DEFINE_FUNC(void, foo, (double x)) {
    return x;
}

... 并自动生成样板。如果在函数上方加上 Register 并借助声明,这实际上非常简单:

#define DEFINE_FUNC(Ret, name, args)   \
    Ret name args;                     \
    Register register_##name##_([] {   \
        return reg(&name, #name, ...); \
    });                                \
    Ret name args

【讨论】:

    【解决方案3】:

    不,没有。这就是你的答案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-21
      • 2019-04-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多