【发布时间】:2017-05-02 16:07:46
【问题描述】:
在开发依赖于另一个第三方库的库时,我遇到了第三方库绝对是垃圾需要手动调用全局设置和清理函数的问题。
int main()
{
setup();
//do stuff
cleanup();
}
现在,这是 一个彻头彻尾的 sh*t show 在应用程序代码中并不是什么大问题,因为它只是在语法上很可怕,但实际上是库中的一个痛苦。
该库应该将这些奇怪的实现细节抽象出来,并且要求用户调用设置函数就像打我自己的脸。
我试图让它们消失
//namespace scope
struct AutoMagic
{
AutoMagic() {setup();}
~AutoMagic() {cleanup();}
};
AutoMagic automagic;
然后我意识到这不会像这里和那里看到的那样跨翻译单元工作
- C++ global initialization order ignores dependencies?
- Is initialization order guaranteed
- C++ Dynamic initialization - across translation units
- Initialization across c++ translation units
- C++ static initialization order
因此标题中的问题。
【问题讨论】:
-
我想这是一个见仁见智的问题,在我看来,手动设置/拆卸是正确的方法。它为该库的用户提供了更多控制权。如果我想/需要在启动该库之前做某事怎么办?如果有一些配置选项可以在启动之前/启动时传递给它怎么办?现在,如果您想自动执行此操作,请继续执行您所做的操作。它会起作用,我的意思是它会在
main开始之前的某个时间调用setup。为什么要关心全局初始化器的顺序? -
@AndreyTurkin 用户可能需要全局变量。在这种情况下,事情会破裂。意见不同,但我不希望我的库带有警告:“你不能有来自这个库的全局变量”,或者“如果在安装之前调用这个库,程序是不正确的”。这种行为也会通过库层传播,这意味着最终用户可能与实际设置相距甚远,以至于代码看起来像一粒尘埃
-
用户可以使用全局变量,除非某些全局构造函数使用该库,否则一切都会正常工作。在这种情况下,您有依赖关系,而可怜的 3rd 方库作者无论如何都没有机会做正确的事情(他/她应该如何处理让您满意?)我知道的唯一选择案例是使用
std::call_once之类的东西检查和初始化每个公共 API 函数中的库。 -
@AndreyTurkin 我的库依赖于第三方库,我需要致电
setup()以使我的库正常工作。如果用户决定他想要一个来自我的库的类型的全局变量,他不能。因为他不知道设置是否完成。我在每个公共 API 中都考虑了类似于std::call_once的内容,但我认为这不会使库非常易于维护和无错误。 -
那么...你的图书馆有一些共享状态吗?让事情变得更有趣 - 使用非平凡的构造函数;比如说,一些受全局互斥体保护的全局缓存?如果没有,想象一下(因为确实如此——第 3 方库的初始化基本上是共享状态)。现在,您将如何确保您的库用户可以在其全局变量中使用您的库 API?现在想象一下,有些库用户希望确保他们的一些代码在您的库执行任何事情之前运行,然后他们希望在您的库清理所有事情之后运行他们的一些代码i>.
标签: c++ initialization raii