我需要创建一个对象,该对象将用于程序的其余部分。因此,它必须是全球性的。但是,它的值必须是某种逻辑的结果(调用某些函数)。推荐的方法是什么?
我能想到的方法是:
MyThing my_global;
bool my_global_is_initialized = false;
void some_function_using_the_global(void) {
if (!my_global_is_initialized) {
my_global = initialize_global();
}
do_stuff_with_global();
}
这种方法是否有问题?有更好的方法吗?
答案 0 :(得分:5)
有几种方法可以做到这一点:
在main
的开头进行初始化。
仅公开函数MyThing *get_global(void)
。然后,全局变量的用户将调用此函数以获得指针。该函数可以执行所需的任何操作,包括在首次调用它时初始化静态变量:
MyThing *get_global(void) {
static MyThing my_global;
static bool is_initialized = false;
if (!is_initialized) {
my_global = initialize_global();
is_initialized = true;
}
return &my_global;
}
((如果需要,您可以在宏#define MyGlobal (*get_global())
后面隐藏此功能的使用,类似于errno
的实现方式。)
某些系统提供了用于启动时自动调用功能的非标准功能,例如__attribute__((constructor))
in gcc:
constructor
属性使函数在执行进入main ()
之前自动被调用。
答案 1 :(得分:3)
您的好方法。我还要标记static
。
您为标志检查付出了很小的运行时间开销,但这可能不是问题(函数调用开销可能会花费更多)。
或者,您可以拥有一个library_init
函数(占位符名称;选择您自己的函数),您需要用户在使用函数之前调用该函数。
不重要的是,在clang / gcc上有__attribute((__constructor__))
,其工作方式类似于library_init
,但在程序/库加载时自动完成。
答案 2 :(得分:0)
如果它是一个全局变量,那么您正在做的是一个反模式,除非存在MyThing
的多个全局实例,并且在这种情况下有多个标志,每个全局变量甚至更糟。
如果MyThing等同于基本的C型,则只需使用超出您的用例范围的值来表示未初始化。
如果是结构,则将初始化标志放在结构内。
如果它是API的一部分,并且您要确保API的用户未修改全局变量,则必须注意使MyThing
不透明。
答案 3 :(得分:-2)
我不能完全确定'MyThing'是什么类型的对象以及可以使用什么初始化该全局变量的值,但是如果您知道例如,initialize_global()函数将永远不会使用该对象初始化'my_global'值(-1),则可以删除多余的全局变量,然后执行以下操作:
#define MYTHING_UNINITIALIZED (-1)
MyThing my_global = MYTHING_UNINITIALIZED;
void some_function_using_the_global(void) {
if (MYTHING_UNINITIALIZED == my_global) {
my_global = initialize_global();
}
do_stuff_with_global();
}