C ++初始化本地/全局对象

时间:2017-08-15 09:59:54

标签: c++

我已经遇到很多时间,例如一个班级,例如LogFile,没有默认构造函数,而我想初始化它的一个实例,而不是在堆上。

以下是一个例子:

LogFile logfile;

void init(const std::string& path) {
    logfile = LogFile(path);
}

上面的代码无法编译,因为LogFile类没有默认构造函数。

我目前使用了一些解决方法:

1。 坚持不要手动进行任何堆调用,将对象存储在列表中(列表肯定会使用堆,但我不会关心它)

std::list<LogFile> logfile_holder;

void init(const std::string& path) {
    logfile_holder.push_back(LogFile(path));
}

2。 使用堆,使用共享指针/唯一指针:

std::shared_ptr<LogFile> logfile_ptr;

void init(const std::string& path) {
    logfile_ptr.reset(new LogFile(path));
}

我有更标准的解决方案来做这些事情吗?

即使看起来像列表解决方法的东西,但是使用专门为此目的指定的模板类,没有列表的开销,也会很好。

3 个答案:

答案 0 :(得分:5)

optional可以替代(stdboost,具体取决于您的编译器版本):

std::optional<LogFile> logfile;

void init(const std::string& path) {
    logfile = LogFile(path);
}

答案 1 :(得分:4)

您可以使用间接。使用全局指针,并使用函数local static:

初始化它
LogFile* logfile_ptr;

void init(const std::string& path) {
    static LogFile logfile(path);
    logfile_ptr = &logfile;
}

对于您的建议,如果您要使用堆,则在使用智能指针时使用列表(或其他数据结构)没有什么意义。

请注意,在此基于您的设计中,您需要注意在初始化之前不要使用全局日志文件。如果不确定,很容易检查指针是否为空。

更简单的方法是简单地添加默认构造函数。如果在设置路径之前使用它,则允许更改Logfile的行为。例如,您可以终止程序并描述错误,或者如果您不关心丢失的过早记录,您可以默默地忽略此类错误。或者您甚至可以将记录存储到缓冲区中,并在路径最终初始化后立即刷新它。

答案 2 :(得分:1)

通常的方法是将Logger类分开并拥有一个Logfile类,这些类在内部耦合并分别负责:

  • Logger类在需要时实例化,用于编写文本格式的日志消息
  • Logfile类负责配置应用程序范围的日志文件。将有一个static类成员代表与所有std::ostream个实例共享的Logger

这是草图:

class Logfile {
    friend class Logger;
    static std::unique_ptr<std::ostream> plogstream_;

public:
    void set_logfile(const std::string& logfile_path) {
    void set_logstream(std::unique_ptr<std::ostream> logstream);
};

Logfile::plogstream_ = std::unique_ptr<std::ostream>(std::cerr,[](void*){});

class Logger {
public:
     operator ostream&()() {
          return *Logfile::plogstream_;
     }
};