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