【问题标题】:Implementing lazy initialisation in C在 C 中实现延迟初始化
【发布时间】:2022-01-02 16:16:58
【问题描述】:

在 C++ 中,我可以使用 static 实现延迟初始化:

struct foo { ... };
foo create_foo();
const foo& get_foo() {
    static foo x = create_foo();
    return x;
}

这里,初始化在第一次调用get_foo 时发生(惰性),get_foo 保证是线程安全的,并且初始化保证只发生一次。具体来说:

[stmt.dcl] "具有静态存储持续时间的块范围变量的动态初始化...在控制第一次通过其声明时执行...如果控制同时进入声明...并发执行应等待初始化完成”

如何在标准 C 中获得相同的行为?

【问题讨论】:

  • 你确定吗?我希望所有静态对象都在 main() 被调用之前被初始化。标准是怎么说的? -- 常见的解决方案是使用初始化为nullptr(C 中为NULL)的指针,然后采取相应的行动。
  • [stmt.dcl] "具有静态存储持续时间的块范围变量的动态初始化......在控制第一次通过其声明时执行......如果控制同时进入声明...... . 并发执行应等待初始化完成"
  • @konsolas,最好用那句话来编辑你的问题。

标签: c lazy-initialization


【解决方案1】:

在 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;
}

【讨论】:

  • Clang 说“错误:初始化元素不是编译时常量”(在填写 ... 并将 static foo 更正为 static struct foo 之后)。这也不会处理并发问题。
  • 让我们做个标志吧!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-10
  • 1970-01-01
  • 2011-11-17
  • 1970-01-01
  • 1970-01-01
  • 2020-10-08
相关资源
最近更新 更多