在 C 中实现惰性初始化
Implementing lazy initialisation in C
在 C++ 中,我可以使用 static
:
实现惰性初始化
struct foo { ... };
foo create_foo();
const foo& get_foo() {
static foo x = create_foo();
return x;
}
这里,初始化发生在第一次调用get_foo
时(惰性),get_foo
保证是线程安全的,并且保证初始化只发生一次。具体来说:
[stmt.dcl] "Dynamic initialization of a block-scope variable with static storage duration ... is performed the first time control passes through its declaration ... if control enters the declaration concurrently ... the concurrent execution shall wait for completion of the initialization"
如何在标准 C 中获得相同的行为?
在 C 中,没有引用,你必须键入 struct
,你必须负责初始化。
#include <stdbool.h>
struct foo { int a; };
struct foo create_foo();
const struct foo* get_foo() {
static bool initialized = false;
static struct foo x;
if (!initialized) {
initialized = true;
x = create_foo();
}
return &x;
}
为了线程安全,可以使用call_once
。可悲的是,有一个全局变量。
#include <threads.h>
struct foo { int a; };
struct foo create_foo();
static struct foo global_x;
static void init_global_x(void) {
global_x = create_foo();
}
const struct foo* get_foo() {
static once_flag global_x_initialized = ONCE_FLAG_INIT;
call_once(&global_x_initialized , init_global_x);
return &global_x;
}
在 C++ 中,我可以使用 static
:
struct foo { ... };
foo create_foo();
const foo& get_foo() {
static foo x = create_foo();
return x;
}
这里,初始化发生在第一次调用get_foo
时(惰性),get_foo
保证是线程安全的,并且保证初始化只发生一次。具体来说:
[stmt.dcl] "Dynamic initialization of a block-scope variable with static storage duration ... is performed the first time control passes through its declaration ... if control enters the declaration concurrently ... the concurrent execution shall wait for completion of the initialization"
如何在标准 C 中获得相同的行为?
在 C 中,没有引用,你必须键入 struct
,你必须负责初始化。
#include <stdbool.h>
struct foo { int a; };
struct foo create_foo();
const struct foo* get_foo() {
static bool initialized = false;
static struct foo x;
if (!initialized) {
initialized = true;
x = create_foo();
}
return &x;
}
为了线程安全,可以使用call_once
。可悲的是,有一个全局变量。
#include <threads.h>
struct foo { int a; };
struct foo create_foo();
static struct foo global_x;
static void init_global_x(void) {
global_x = create_foo();
}
const struct foo* get_foo() {
static once_flag global_x_initialized = ONCE_FLAG_INIT;
call_once(&global_x_initialized , init_global_x);
return &global_x;
}