库初始化和关闭的常见模式?

jdt*_*141 9 c++ design-patterns

是否有一种模式可用于调用底层(C)库的必需初始化和清理例程?在我的例子中,我想创建包装类,以便它可以组成其他对象.问题是,当我销毁包装类时,会调用底层库的清理例程.这很好,直到我实例化我的包装类的多个对象.我的问题是,真正处理这种情况的最佳方法是什么?我想到了静态参考计数器,但我想知道是否还有其他可能更好的选择和涉及的交易.

Emi*_*ier 6

如果可以在 main 开始之前调用初始化,并且在 main 结束之后调用清理,这个小技巧(hack?)可能对你有用:

#include <iostream>

// C library initialization routine
void init() {std::cout << "init\n";}

// C library cleanup routine
void fini() {std::cout << "fini\n";}

// Put this in only one of your *.cpp files
namespace // anonymous
{
    struct Cleaner
    {
        Cleaner() {init();}
        ~Cleaner() {fini();}
    };
    Cleaner cleaner;
};

int main()
{
    std::cout << "using library\n";
}
Run Code Online (Sandbox Code Playgroud)

输出:

init
using library
fini
Run Code Online (Sandbox Code Playgroud)

它使用(滥用?)静态对象的构造函数在 main 之前调用,而析构函数在 main 之后调用的事实。这就像整个程序的 RAII。

  • 也谷歌静态初始化顺序惨败。例如,在 `init` 和 `fini` 中使用 `std::cout` 让这个 C++ 菜鸟感到紧张:它是否保证已经/仍然存在? (7认同)

War*_*ung 5

并不是所有的事情都必须是一个类。单例模式可以让你把它变成一个类,但它实际上并没有给你带来任何超过全局函数的东西:

bool my_library_init();
void my_library_shutdown();
Run Code Online (Sandbox Code Playgroud)

如果库已成功初始化,第一个调用将返回 true,第二个调用只是安静地执行任何需要执行的操作并退出。您可以在您喜欢的这些接口后面添加任何引用计数或线程跟踪类型的内容。

另外,不要忽视您的图书馆可能能够透明地完成所有这些工作的可能性。当调用第一个库函数时,它是否可以检测到它尚未初始化并在执行工作之前设置所有内容?对于关闭,只需将要销毁的资源注册到全局对象中,这样它们就会在程序退出时被销毁。这样做当然比较棘手,但对于库的调用者来说可能值得获得可用性优势。