C ++库中的自动初始化例程?

时间:2010-04-30 20:56:54

标签: c++ initialization

如果我有一个头文件foo.h和一个源文件foo.cpp,并且foo.cpp包含以下内容:

#ifdef WIN32
class asdf {
   asdf() { startup_code(); }
   ~asdf() { cleanup_code(); }
};
asdf __STARTUP_HANDLE__
#else
//unix does not require startup or cleanup code in this case
#endif

但是foo.h没有定义类asdf,比如我有一个应用程序bar.cpp:

#include "foo.h"
//link in foo.lib, foo.dll, foo.so, etc
int main() {
   //do stuff
   return 0;
}

如果bar.cpp是在WIN32平台上编译的,那么asdf()和~asdf()会在适当的时间(分别在main()之前和程序退出时)调用,即使类asdf没有在foo.h,但通过foo.cpp链接?

4 个答案:

答案 0 :(得分:5)

是的 - 但要非常小心。初始化静态对象(如asdf对象)的顺序未定义。因此,如果任何其他对象试图在main()之前引用您的对象,则它是未定义的行为。

此外,__STARTUP_HANDLE__不是有效的标识符。任何标识符(甚至是宏)都不允许使用双下划线,也不允许使用单下划线后跟大写字母。

答案 1 :(得分:1)

如果没有损坏,请不要修理它。请注意静态初始化顺序问题,正如其他答案所说。但你真的应该修复那个保留的标识符。

__STARTUP_HANDLE__的工作方式类似于运行时库,运行时库使用这样的名称,但它不是运行时库的一部分,因此不允许使用该名称。

#ifdef WIN32
namespace { // anonymous namespace - no outside access
class asdf {
   asdf() { startup_code(); }
   ~asdf() { cleanup_code(); }
} x; // to create an instance
}

答案 2 :(得分:0)

只要对象(foo.o)本身链接到可执行文件中,这将起作用(假设静态初始化顺序fiasco没有击中你)。但是,如果你从库(foo.lib)中提取它,除非你明确地将对象标记为“活动对象”,否则它将不会,但我不记得如何在MSVC中这样做。

答案 3 :(得分:0)

在Windows上,使用DLL,您可以使用将在加载时调用的函数DllMain

BOOL WINAPI DllMain(HINSTANCE hinstDLL,
                    DWORD fdwReason,
                    LPVOID lpvReserved) {  

  switch (fdwReason) {

  case DLL_PROCESS_ATTACH:    
    break;

  case DLL_THREAD_ATTACH:
    break;

  case DLL_THREAD_DETACH:
    break;

  case DLL_PROCESS_DETACH:
    break;

  default:
    break;
  }

  return TRUE;
}