我正在寻找一个std::ostream
像/dev/null
. 它只会忽略流向它的任何内容。标准库或 Boost 中是否存在这样的东西?还是我必须自己动手?
9 回答
最简单的解决方案就是使用未打开的std::ofstream
. 这将导致流中的错误状态,但大多数输出器不会检查这一点;通常的习惯用法是在关闭之后将检查留到最后(这会将其放入您编写的代码中,您知道流应该是无效的)。
否则,实现起来非常简单:只需创建一个
streambuf
包含一个小缓冲区的,并将其设置为overflow
(总是返回成功)。但是请注意,这将比未打开的文件慢;各种>>
运算符仍将进行所有转换(如果流具有错误状态,他们不会这样做)。
编辑:
class NulStreambuf : public std::streambuf
{
char dummyBuffer[ 64 ];
protected:
virtual int overflow( int c )
{
setp( dummyBuffer, dummyBuffer + sizeof( dummyBuffer ) );
return (c == traits_type::eof()) ? '\0' : c;
}
};
通常提供一个从istream
or派生的便利类ostream
,它将包含它使用的这个缓冲区的一个实例。类似于以下内容:
class NulOStream : private NulStreambuf, public std::ostream
{
public:
NulOStream() : std::ostream( this ) {}
NulStreambuf* rdbuf() const { return this; }
};
或者你可以只使用一个std::ostream
,将streambuf的地址传递给它。
如果你有 boost,那么 boost/iostreams/device/null.hpp 中有一个 null ostream 和 istream 实现。它的要点:
#include "boost/iostreams/stream.hpp"
#include "boost/iostreams/device/null.hpp"
...
boost::iostreams::stream< boost::iostreams::null_sink > nullOstream( ( boost::iostreams::null_sink() ) );
...
如果你badbit
在一个流上设置它不会输出任何东西:
#include <iostream>
int main() {
std::cout << "a\n";
std::cout.setstate(std::ios_base::badbit);
std::cout << "b\n";
std::cout.clear();
std::cout << "c\n";
}
输出:
a
c
我知道这是一个非常古老的线程,但我想将此添加给任何正在寻找相同解决方案但没有提升和最快解决方案的人。
我结合了上面的三个不同的建议,一个直接写入 /dev/null (所以它涉及内核。)
令人惊讶的是,得票最多的 NullStream 表现最差。
以下是 100,000,000 次写入的结果:
a) /dev/null : 30 seconds
b) NullStream: 50 seconds
c) badbit : 16 seconds (the winner in speed, but cannot test for errors!)
d) boost : 25 seconds (the ultimate winner)
这是测试代码
#include <iostream>
#include <fstream>
#include <time.h>
#include <boost/iostreams/stream.hpp>
class NullStream : public std::ostream {
class NullBuffer : public std::streambuf {
public:
int overflow( int c ) { return c; }
} m_nb;
public:
NullStream() : std::ostream( &m_nb ) {}
};
int test( std::ostream& ofs, const char* who ) {
const time_t t = time(NULL);
for ( int i = 0 ; i < 1000000000 ; i++ )
ofs << "Say the same" ;
std::cout << who << ": " << time(NULL) - t << std::endl;
}
void devnull() {
std::ofstream ofs;
ofs.open( "/dev/null", std::ofstream::out | std::ofstream::app );
test(ofs, __FUNCTION__);
ofs.close();
}
void nullstream() {
NullStream ofs;
test(ofs, __FUNCTION__);
}
void badbit() {
std::ofstream ofs;
ofs.setstate(std::ios_base::badbit);
test(ofs, __FUNCTION__);
}
void boostnull() {
boost::iostreams::stream< boost::iostreams::null_sink > nullOstream( ( boost::iostreams::null_sink() ) );
test(nullOstream, __FUNCTION__);
}
int main() {
devnull();
nullstream();
badbit();
boostnull();
return 0;
}
编辑
最快的解决方案——我们使用 badbit 的地方——有一个缺点。如果程序检查输出是否成功写入——我不知道为什么程序不应该这样做——那么它会因为这个坏位而失败。因此,亚军 -提升- 是赢家。
在@user5406764 的回答之后,可以通过重载全局<<
运算符来跳过任何实际操作。解决方案应该是跨平台的,并且是最快的。
#include <iostream>
class NullStream : public std::ostream {
public:
NullStream() : std::ostream(nullptr) {}
NullStream(const NullStream &) : std::ostream(nullptr) {}
};
template <class T>
const NullStream &operator<<(NullStream &&os, const T &value) {
return os;
}
int main() {
auto null = NullStream();
std::cerr << "a" << std::endl;
null << "b" << std::endl;
std::cerr << "c" << std::endl;
}
输出:
a
c
struct NullStream // only subclass std::stream if you must
{
template<typename T>
NullStream& operator<<(T const&) { return *this; }
};
NullStream TheNullStream; // There's your global instance
至于我,最简单的方法是:
#include <fstream>
std::ostream* out = &std::cout;
std::ostream* nullstream() {
static std::ofstream os;
if (!os.is_open())
os.open("/dev/null", std::ofstream::out | std::ofstream::app);
return &os;
}
int main() {
*out << "Normal output\n";
out = nullstream();
*out << "Will not visible\n";
out = &std::cout;
*out << "Back again\n";
return 0;
}
或者如上所述在“nullstream”函数中使用“badbit”标志而不是“/dev/null”。
std::ostream* nullstream() {
static std::ofstream os;
static bool flag_set = false;
if (!flag_set) {
os.setstate(std::ios_base::badbit);
flag_set = true;
}
return &os;
}
愿此解决方案在不使用 boost 的情况下克服性能问题:
#include <ostream>
class dev0_buffer : public std::streambuf
{
//called usually for n-characters
std::streamsize xsputn (const char* s, std::streamsize n) override { return n; }
//may not required due it's not called anymore
int overflow (int c) override { return c; }
} nirwana;
class dev0_stream : public std::ostream
{
public:
dev0_stream(): std::ostream(&nirwana){}
};