【问题标题】:Calling void function before main()在 main() 之前调用 void 函数
【发布时间】:2017-08-26 07:31:37
【问题描述】:

我想知道是否可以不使用使用临时变量来调用 void 函数。例如。在下面的代码块中...

#include <iostream>

void earlyInit()
{
  std::cout << "The void before the world." << std::endl;
}

int g_foo = (earlyInit(), 0);

int main( int argc, char* argv[] )
{
  std::cout << "Hello, world!" << std::endl;
}

...我不需要g_foo,宁愿它不存在。有没有办法在没有中间临时变量的情况下调用 void 函数?

【问题讨论】:

  • 你刚刚问了这个然后删除了它。为什么?
  • 您是否考虑过类似于延迟加载的 Meyers Singleton 的方法?
  • @NeilButterworth 因为我很愚蠢。对不起。真心忏悔。
  • @user4581301 我认为您指出的设计模式仍然需要一个单例对象的静态初始化,不是吗?如果没有,请发布更多详细信息。我的问题的症结在于是否可以在没有临时变量的情况下调用main() 之前的函数。
  • " 我的问题的症结在于是否可以在没有临时变量的 main() 之前调用函数" - 答案是可移植的?没有。

标签: c++ static-initialization


【解决方案1】:

我想知道是否可以在不使用临时变量的情况下调用 void 函数。例如。在下面的代码块中。

该语言不提供任何此类机制。正如其他答案所指出的那样,可能有特定于编译器的方法可以做到这一点。

但是,我认为您的方法没有任何问题。我经常使用以下模式。

#include <iostream>

namespace mainNS  // A file-specific namespace.
{
   void earlyInit()
   {
      std::cout << "The void before the world." << std::endl;
   }

   struct Initializer
   {
      Initializer();
   };
}

using namespace mainNS;
static Initializer initializer;

Initializer::Initializer()
{
   earlyInit();
   // Call any other functions that makes sense for your application.
}

int main( int argc, char* argv[] )
{
  std::cout << "Hello, world!" << std::endl;
}

【讨论】:

    【解决方案2】:

    检查您的编译器是否支持#pragma startup(或等效),例如:

    #include <iostream>
    
    void earlyInit()
    {
      std::cout << "The void before the world." << std::endl;
    }
    #pragma startup earlyInit
    
    int main( int argc, char* argv[] )
    {
      std::cout << "Hello, world!" << std::endl;
    }
    

    【讨论】:

    • 看起来很有希望,但我的编译器似乎不支持这一点。 Code Chef 也没有。这是对哪个编译器的扩展?
    • @StoneThrow:您实际使用的是哪个编译器?不同的编译器支持不同的东西。 bcc 支持#pragma startup,VC++ 支持#pragma init_seg,gcc 和clang 支持__attribute__((constructor))。等等。这就是为什么我在回答中说“(或同等)”。
    • g++ (GCC) 4.8.3 20140911 (Red Hat 4.8.3-7)。不要取笑我!我知道它已经过时了,但它超出了我的控制范围。
    【解决方案3】:

    this question 的答案引起了我的注意,__attribute__((constructor)) 引起了我的注意,但是,由于我不完全理解的原因,如果 void 函数使用了 std::coutprintf不会导致SIGSEGV)。

    我早些时候发布了这个问题的一个版本(但愚蠢地删除了它)。当时的一位回答者向我指出了这篇讨论情况和解决方案的优秀文章:

    http://dbp-consulting.com/tutorials/debugging/linuxProgramStartup.html

    解决方案的摘录(稍作修改以通过编译)在这里:

    #include <cstdio>
    #include <cstdlib>
    
    void preinit(int argc, char * * argv, char * * envp) {
      printf("%s\n", __FUNCTION__);
    }
    void init(int argc, char * * argv, char * * envp) {
      printf("%s\n", __FUNCTION__);
    }
    
    void fini() {
      printf("%s\n", __FUNCTION__);
    }
    __attribute__((section(".init_array"))) typeof (init) * __init = init;
    __attribute__((section(".preinit_array"))) typeof (preinit) * __preinit = preinit;
    __attribute__((section(".fini_array"))) typeof (fini) * __fini = fini;
    
    void __attribute__((constructor)) constructor() {
      printf("%s\n", __FUNCTION__);
    }
    
    void __attribute__((destructor)) destructor() {
      printf("%s\n", __FUNCTION__);
    }
    
    void my_atexit() {
      printf("%s\n", __FUNCTION__);
    }
    
    void my_atexit2() {
      printf("%s\n", __FUNCTION__);
    }
    
    int main() {
      atexit(my_atexit);
      atexit(my_atexit2);
    }
    

    (向原始回复者道歉,我删除了我的原始帖子并且无法给予应有的信任。)

    【讨论】:

    • 更新了代码摘录以通过 gcc-4.9.1 编译。
    • std::cout 是专门初始化的。也许由于某种原因,这个属性在静态初始化完成之前运行函数。
    猜你喜欢
    • 2011-07-10
    • 2020-04-07
    • 2022-10-04
    • 2012-12-06
    • 2012-06-09
    • 1970-01-01
    • 2011-06-20
    • 1970-01-01
    • 2010-09-16
    相关资源
    最近更新 更多