隐藏初始化代码 "before main" 是好习惯吗?

Is it good practice to hide Initialization code "before main"?

我正在构建一个 c++ 库,我需要为我的程序(和其他默认资源对象)初始化一个 openGL 上下文。在 main 之前调用的代码块中 "hide the Init. code" 是否是好的做法(考虑现代 c++ 语义)?我不能使用静态变量,因为我需要按特定顺序初始化事物! (我不能在 openGLm 或 SDL 之前初始化纹理!)

这是我的代码:

#include <stdio.h>

#ifdef _MSC_VER // For msvc / msvc++ 2015

#define CCALL __cdecl
#pragma section(".CRT$XCU",read)
#define INITIALIZER(f) \
   static void __cdecl f(void); \
   __declspec(allocate(".CRT$XCU")) void (__cdecl*f##_)(void) = f; \
   static void __cdecl f(void)

#elif defined(__GNUC__) for gcc / g++

#define CCALL
#define INITIALIZER(f) \
   static void f(void) __attribute__((constructor)); \
   static void f(void)

#endif

static void CCALL finalize(void)
{
    /* Some king of delete / dispose here : like SDL_Quit, ... */
}

INITIALIZER(initialize)
{
/* 
   HERE IS THE STARTUP CODE ...

*/

}

Would it be good practice ( considering modern c++ semantics ) to "hide the Init. code" in a code chunk being called before main ?

main 之前 运行 任何事情的唯一方法是在静态对象的构造函数中进行。

I cannot use static variables

您 运行 别无选择。在标准 C++ 中无法实现您的要求。

回答这样的问题是否是好的做法...这是基于意见的,但我要说的是,如果库在我明确告诉它初始化之前就初始化了某些东西,我通常会认为这是不好的。这将阻止库的用户控制您的库相对于其他库的初始化顺序。当您的库依赖于 SDL 等其他库时,这一点尤为重要。

标准第 3.6.2 节指出,非局部静态变量 可以 main 的第一条语句之前初始化:

It is implementation-defined whether the dynamic initialization of a non-local variable with static storage duration is done before the first statement of main.

因此,它并没有说它们必须main的第一个语句之前被初始化。在 C++ 中没有办法强制约束在调用 main() 之前初始化任何东西,除了在与 main.

相同的编译单元中定义的静态变量。

最好的解决方案就是将您的资源管理包含在 main 本身中:

int main()
{
    // Load resources (housekeeping code)

    // Do real work (applicative code)

    // Release resources (housekeeping code)
}

如果要将应用代码与内务代码分开,常用的方法是使用inversion of control (sometimes via a template method pattern):

  • 单独的函数或方法专用于应用程序或用户代码
  • 函数 main 负责执行内务处理和调用用户代码或应用代码函数或方法。

举例如下:

// The function below is expected to exist by the framework
// It must be implemented by the user
int userMain()
{
    // Implement user-code here
}

// The code below is implemented by the framework
// It expects the user to have implemented a function userMain
int main()
{
    FrameWorkData theFrameWorkData;

    // The framework performs its initialization house-keeping here
    theFrameWorkData.initialize();

    // The framework invokes the user-code (inversion of control)
    userMain();

    // The framework performs its clean-up house-keeping here
    theFrameWorkData.cleanup();
}

Would it be good practice ( considering modern c++ semantics ) to "hide the Init. code" in a code chunk being called before main ?

因为不能保证全局静态对象的初始化顺序,所以我通常认为这种做法很糟糕。另一个原因 - 为此类代码提供诊断并非易事,并且会产生人为问题,无需使用此方法即可轻松避免。有例外,但它们很少见,绝对没有那么多的人认为这是一个好的做法。