确保全局记录器对象比其他全局对象更长寿

时间:2013-07-01 13:06:43

标签: c++ singleton global-variables shared-ptr

我有一些带有一些单例对象的应用程序。他们希望在构造和销毁时编写日志消息,这在全局变量的初始化时发生。现在,日志记录提供程序也是一个单例对象,如下所示:

// loggingProvider.h
class LoggingProvider {
    static boost::shared_ptr<LoggingProvider> instance;
public:
    static boost::shared_ptr<LoggingProvider> getInstance();
    /* ... */
};

// loggingProvider.cpp
boost::shared_ptr<LoggingProvider> LoggingProvider::instance;

boost::shared_ptr<LoggingProvider> getInstance() {
    if (!instance) {
        instance.reset(new LoggingProvider());
    }
    return instance;
}

记录器界面如下所示:

// logger.h
class Logger {
    const boost::shared_ptr<LoggingProvider> provider;
    const std::string prefix;
public:
    Logger(const std::string prefix);
    /* ... */
}

// logger.cpp
Logger::Logger(const std::string& prefix) :
        provider(LoggingProvider::getInstance()), prefix(prefix) {}

我们的想法是能够将记录器声明为多个cpp文件中的全局变量,并确保在所有记录器被销毁后销毁日志记录提供程序,因为它由{{1}管理}。如果我在文件的顶部声明这样的记录器,则保证在同一文件中的任何单个对象之后被破坏:

boost::shared_ptr

可悲的是,这段代码不起作用。当我调试它时,// somewhere.cpp static Logger logger("Somewhere"); 的实例被多次创建。我相信情况就是这样,因为LoggingProvider字段实际上是在一些记录器声明之后初始化的。现在我知道没有办法控制跨文件的全局变量的初始化,那么还有另一种方法可以让它工作吗?

1 个答案:

答案 0 :(得分:1)

只需使用经典的单身成语。你不想要 shared_ptr在这里,因为你不想破坏它 对象,永远。基本上,像:

class LoggingProvider
{
    static LoggingProvider* our_instance;
public:
    static LoggingProvider& instance();
    //  ...
};

LoggingProvider* LoggingProvider::our_instance
        = &LoggingProvider::instance();

LoggingProvider&
LoggingProvider::instance()
{
    if ( our_instance == NULL ) {
        our_instance = new LoggingProvider;
    }
    return *our_instance;
}

这里重要的事情是1)指针没有任何重要的意义 构造函数,以及2)实例永远不会被破坏。

有一件事:因为你输出的任何文件永远不会 关闭,确保刷新所有输出。 (我通常这样做 使用实际记录器的短期临时实例, 从LoggerProvider获取目标streambuf, 并在它们的析构函数中刷新它。)