写入未打开的流

时间:2015-02-04 21:56:47

标签: c++ io ofstream

我的应用程序需要非常简单的记录器。但有时候我不想使用这个记录器加速我的应用程序。

我的记录器看起来像:

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;的行为是什么?运营商,如果我没有打开文件?安全吗?它速度快吗?这是个好主意吗?

3 个答案:

答案 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秒。因此,如果你担心性能问题,那么你可能应该首先解决的问题是,如果你不是绝对需要它,那么重复输出就会出现。

相关问题