在main()函数之前或之后运行函数的时机是什么?

6
GCC支持构造函数/析构函数,这些函数支持在main()之前或之后运行函数:

constructor属性会导致该函数在进入main()之前自动调用。同样,destructor属性会导致该函数在main()完成或exit()被调用后自动调用。具有这些属性的函数可用于初始化在程序执行期间隐式使用的数据。

这里是GeeksforGeeks的一个例子。

什么情况下使用此功能最合适?特别是要在main()之前调用函数,如果我们只将其放置在main()的开头,有什么区别?

4个回答

2

编写库时,这样的构造函数和析构函数非常有用。

如果您正在编写需要初始化的库,那么您必须提供一个初始化函数。但是,如何确保在库的任何其他函数之前运行它?使用该库的用户必须记得调用它,而他们很容易忘记。

自动完成初始化的一种方法是将函数标记为构造函数。

另请参阅:如何在Linux上初始化共享库


为什么不使用简单的静态初始化呢?总的来说,我会对在显式初始化之前执行任何工作的库持怀疑态度。库编写者不应该为库用户决定何时需要初始化库。 - mockinterface

1
假设您有一个全局结构,并且希望在启动程序之前将内存初始化到该结构中,您可以将其放在构造函数中,因为它会在main()之前调用。
同样地,如果您想在程序结束之前释放任何现有的内存,可以在析构函数中这么做。

如果我们只是将构造函数放在main的开头,有什么区别吗? - chux - Reinstate Monica
此外,程序正在使用的任何内存都将在退出时释放。 - George

1

对于大多数情况来说,没有任何区别。你想要使用全局变量、单例、内存等做的所有事情,在main()中和普通的静态初始化器中理论上都可以实现。

这种情况稍微适用的主要场景是跨平台项目,你希望将大部分共享代码放在main函数中,但在某些平台(主要是嵌入式平台)上,你希望在main函数之前复制其他操作系统所做的工作 - 设置环境变量、将标准文件描述符(stdin/stdout/stderr)与系统上的自定义描述符连接起来、分配自己的自定义内存管理器 - 例如为运行main()分配自己的堆栈等。


1
从我的角度来看,模块构造函数在制作共享模块时才有意义。
共享模块没有特定的初始化程序(在Windows上有DllMain,但它有其限制)。
例如,Asterisk PBX滥用构造函数,因为它强烈依赖于模块,在编译时向每个模块注入构造函数。这个构造函数在dlload()上调用,并告诉asterisk核心模块是否已经正确加载,从而允许调用模块上的特定函数。

实际上,这个概念同样适用于共享库和静态链接库。 - harmic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接