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

C++ initialization of local/global object

本文关键字:初始化 对象 全局 本地 C++      更新时间:2023-10-16

我已经遇到过很多次有类的情况,例如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));
}

阿拉伯数字。 使用堆,使用共享指针/唯一指针:

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

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

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

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

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

您可以使用间接寻址。使用全局指针,并使用函数 local static 对其进行初始化:

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

对于您的建议,如果要使用堆,则可以使用智能指针,则使用列表(或其他数据结构(几乎没有意义。

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

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

通常的方法是分离一个Logger类,并拥有一个内部耦合的Logfile类,并分离职责:

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

这是草图:

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_;
}
};