使用静态数据的构造函数在main()之前执行工作

Using constructor of static data to perform work before main()

本文关键字:工作 执行 main 静态 数据 构造函数      更新时间:2023-10-16

我们的系统有一个基于插件的架构,每个模块有效地有一个'主'功能。我需要在调用模块的main()之前运行一小段代码。我已经成功地将代码放入一个虚拟类的构造函数中,然后声明该类的一个静态变量,例如:

namespace {
class Dummy {
public:
    Dummy() { /* do work here */ }
};
   Dummy theDummy;
}
void main() {...}

这似乎工作得很好,但它是一个有效的解决方案,在编译器保证代码将运行?它是否有机会检测到theDummy在系统中的其他任何地方都没有被引用,并将其编译/链接完全删除,或者它会意识到构造函数需要运行?由于

这似乎工作得很好,但它是一个有效的解决方案,在编译器保证代码将运行?它是否有机会检测到dummy在系统中的其他任何地方都没有被引用,并将其编译/链接完全删除,或者它会意识到构造函数需要运行?

参见n3797 S3.7.1/2:

如果具有静态存储时间的变量具有初始化或具有副作用的析构函数,则即使它看起来未使用,也不应消除它,

是的,初始化必须运行。不能直接省略。

看到S3.6.2/4:

具有静态存储时间的非局部变量的动态初始化是否在main的第一条语句之前完成,这是由实现定义的。如果初始化延迟到main语句第一个语句之后的某个时间点,则初始化应发生在与待初始化变量在同一翻译单元中定义的任何函数或变量第一次使用(3.2)之前。

是的,初始化必须在任何代码在同一翻译单元中运行之前完成。

在你的插件中使用一个名为main()的入口点并不是特别重要。

你可以走了。


根据评论,您确实需要确保您的Dummy构造函数和main函数在相同的翻译单元中才能正常工作。如果它们单独编译并仅链接在一起,则此保证将不适用。

不要调用函数main(),除非它是程序入口点。如果是,那么可以保证静态对象构造函数将在main()之前被调用。

一旦main启动,它保证在使用同一翻译单元中的任何函数或变量之前运行。

因此,如果像这里一样,它和main在同一个翻译单元中,那么它就保证在main之前运行。如果它在另一个事务单元中,那么它是由实现定义的,它是否会在main之前运行。在最坏的情况下,如果程序没有使用来自相同翻译单元的任何内容,它可能根本无法运行。

一般来说,只有当编译器能够确定语义相同时,才允许编译器优化某些内容。因此,如果您调用任何它无法看到的函数,例如,那么它必须假设该函数有副作用,并且不会优化代码。

注意,转换单元之间可能存在初始化顺序问题,因为tu之间静态对象的初始化顺序通常不能保证。但是,可以保证在输入模块的"main"之前调用构造函数(假设相同的TU)。详细信息请参见c++ 11标准第3.6.2节。

如果平台特定的机制适合您,请考虑使用函数属性,这是由g++和clang++支持的