c++ 如何避免延迟静态存储持续时间变量的初始化?

a1o7rhls  于 2023-05-08  发布在  其他
关注(0)|答案(1)|浏览(125)

我有一些在构造函数中有副作用的类,这些类的对象是具有静态存储持续时间的全局对象。在初始化过程中,这些对象在一个特殊的Map中注册它们的类,在这个Map被用于其他目的之前进行这些注册是很重要的。
类及其全局对象在单独的翻译单元中定义,并且根据非块变量规则的动态初始化,初始化可以被推迟,直到来自这些翻译单元的其他函数或变量被使用,并且这可能意味着初始化被无限期地推迟。
我正在寻找一种方法来避免这些全局对象的延迟初始化。我的意思是,对象的构造函数应该在main之前或之后调用,但所有的更改都应该在这些对象的转换单元内完成。换句话说,每当添加具有全局对象的一个或多个翻译单元时,不应修改其他翻译单元。

**更新:**以下是一个例子:

struct Base {
};

extern void regFactoryMethod(std::function<std::shared_ptr<Base>()>);

struct Object : Base {
    struct Registrator {
        Registrator() {
            regFactoryMethod([](){ return std::make_shared<Object>(); });
        }
    };
    static Registrator registrator;
};

Object::Registrator Object::registrator;

这个想法是自动调用Object::Registrator::Registrator()。但不能保证它会,因为这个电话可能会推迟:
具有静态存储持续时间的非块非内联变量的动态初始化是否在main的第一个语句之前排序或延迟,由实现定义。如果它被延迟,它强烈地发生在任何非初始化odr之前-使用任何非内联函数或非内联变量,这些函数或非内联变量定义在与要初始化的变量相同的转换单元中。它是实现定义的,在程序中的哪些线程和哪些点发生这种延迟的动态初始化。

06odsfpq

06odsfpq1#

正如你在问题中提到的,动态初始化是否推迟到第一次非初始化或直接或间接通过main使用非内联转换单元函数/变量是由实现定义的。
在输入main之前,也没有其他标准方法来执行代码。
所以,我不认为你可以得到一个保证,工作独立的实现。该标准还涵盖了一些用例,例如在运行时动态加载库,例如dlopen。在这些情况下,在输入main之前,无法执行库中包含的代码。
您必须寻找实现保证或特定于实现的特性。例如Linux上的GCC/binutils,只要你不链接--as-needed--gc-sections等,并且忽略dlopen,我认为不会有任何延迟初始化。

相关问题