我的应用程序需要非常简单的记录器。但有时候我不想使用这个记录器加速我的应用程序。
我的记录器看起来像:
class Logger
{
public:
Logger(bool isActive = true)
{
mIsActive = isActive;
if (isActive)
{
out.open(pathToLogFile);
}
}
static std::ofstream& log()
{
return out;
}
private:
static bool mIsActive;
static std::ofstream out;
};
在我的应用程序中,我将其用作:
Logger(true); // in one place
Logger::log() << "Log" << std::endl;
如果我不想使用此记录器怎么办?
Logger(false); // in one place. it doesn't open any file.
Logger::log() << "Log" << std::endl; // it shouldn't write anywhere
&lt;&lt;的行为是什么?运营商,如果我没有打开文件?安全吗?它速度快吗?这是个好主意吗?
答案 0 :(得分:2)
您的记录器存在一些问题。
如果在已停用的记录器上使用operator<<
,则不会发生任何事情,但out
流的状态将设置为失败,并且会一直保留,直到您重置它为止。这意味着如果您随后对您的记录器进行反应,则不会再向其写入任何内容。
如果您在记录器已经处于活动状态时重新激活记录器,那么同样如此:out.open()
也会失败并且不会再写入任何内容。
如果您想保留此设计,则必须更新记录器,并检查构造函数是否已out
已打开(使用out.is_open()
),如果需要{{} 3}}错误标志。
<强> 附录: 强>
如果您担心在停用记录器时会不必要地处理假设输出的所有这些<<
的性能,那么您可以考虑为记录器类使用自定义operator<<
,这将考虑mIsActive
1}}。这个clear()
在另一个问题上展示了它是如何运作的。
答案 1 :(得分:0)
无论如何,你的方法都有太多的开销。只需使用ostream:
std::ostream logger(0);
为了写入它,像往常一样使用插入器,但您也可以检查是否有任何连接以避免开销:
if(logger)
logger << "some output" << endl;
现在,为了将输出定向到某处,您可以附加一个streambuffer:
logger.rdbuf(cout.rdbuf()); // redirect to stdout
您还可以将文件用作目标:
logger.rdbuf(new filebuf("log.text", ios_base::out)); // redirect to a file
免责声明:我没有查找文件制作创建的确切参数,但仍然希望您明白这一点。
答案 2 :(得分:0)
我运行了一个非常简单的基准:
void
do_log(std::ostream& os)
{
for (long i = 0L; i < 100000000L; ++i)
os << i << "\n";
}
将其传递为默认构造的std::ofstream
(未连接到任何文件)
std::ofstream sink {};
do_log(sink);
使程序(使用GCC 4.9编译,-O3
优化级别)需要3.1秒才能完成。相反,我将输出连接到/dev/null
std::ofstream sink {"/dev/null"};
do_log(sink);
它需要14.2秒,超过四倍。所以,是的,写入无效流似乎非常有效。
但请注意,上述代码与您的示例不同。如果我把它写成
void
do_log(std::ostream& os)
{
for (long i = 0L; i < 100000000L; ++i)
os << i << std::endl;
}
相反,如果流断开连接需要3.7秒(这是有道理的,因为无论如何都会丢弃写入的内容)但如果连接到/dev/null
则为35.5秒。因此,如果你担心性能问题,那么你可能应该首先解决的问题是,如果你不是绝对需要它,那么重复输出就会出现。