我正在使用的一个软件库向std::cerr
写入了大量调试输出,但如果我让它安静下来,它会将输出重定向到一个空流。这是一个简化的main.cpp
,展示了代码如何尝试实现这一点:
#include <iostream>
#include <fstream>
#include <cassert>
// The stream that debug output is sent to. By default
// this points to std::cerr.
std::ostream* debugStream(&std::cerr);
// Throughout the library's codebase this function is called
// to get the stream that debug output should be sent to.
std::ostream& DebugStream()
{
return *debugStream;
}
// Null stream. This file stream will never be opened and acts
// as a null stream for DebugStream().
std::ofstream nullStream;
// Redirects debug output to the null stream
void BeQuiet()
{
debugStream = &nullStream;
}
int main(int argc, char** argv)
{
DebugStream() << "foo" << std::endl;
BeQuiet();
DebugStream() << "bar" << std::endl;
assert(debugStream->good());
return 0;
}
当你运行这个程序时,你会注意到字符串“bar”被正确地发送到了null流。然而,我注意到Assert失败了。这是我应该关心的事情吗?或者这只是库开发人员所选择的方法的一个稍微丑陋的细节?
如果您愿意,欢迎您提出更好的替代方案。
- 这个库是跨平台的,所以我认为使用开放的
/dev/null
不是一个有效的解决方案,因为它不能在Windows上工作 - 该库使用标准的C++,因此任何替代解决方案都不应使用特定于编译器的内容
2条答案
按热度按时间w7t8yxp51#
没有真实的担心流不是
good()
!因为输出操作符实际上并不对失败模式下的流做任何事情,所以记录的不同实体没有格式化,也就是说,与其他方法相比,代码运行得更快。请注意,您实际上并不需要第二个流来禁用输出:
1.假设所有的输出操作符都表现良好,您只需设置
std::ios_base::failbit
:1.如果有错误的输出写入流,即使它不是
good()
,您也可以将其流缓冲区设置为null:调试流().rdbuf(空指针);
如果你真的希望你的流保持
good()
状态,你需要安装一个只消耗字符的流缓冲区。但是,注意,你需要给予这个流缓冲区一个缓冲区,因为为每个char
调用overflow()
是相当昂贵的。有必要重置流的流缓冲区,因为
std::ostream
的析构函数将刷新stresm缓冲区(即,它调用pubsync()
)。就我个人而言,我会选择设置
std::ios_base::failbit
。ikfrs5lh2#
在this answer中,你可以找到一个通用的帮助器来将任何流重定向到任何其他流:
现在你所需要的只是一个来自this answer的无操作流,它会丢弃所有内容:
你就可以走了
最后,这里有一个live example,如果你想尝试一下的话,这个方法还有一个额外的好处,那就是你(和你的同事)仍然可以在代码中使用
std::cerr
,而且你可以随意地关闭它,然后再打开它:)