c++或库中是否存在null std::ostream实现?
Is there a null std::ostream implementation in C++ or libraries?
我正在寻找像/dev/null
一样的std::ostream
实现。它会忽略任何流到它的内容。这样的东西存在于标准库或Boost中吗?还是我得自己卷?
如果你有boost,那么有一个空流&Istream实现在boost/iostreams/device/null.hpp中可用。要点:
#include "boost/iostreams/stream.hpp"
#include "boost/iostreams/device/null.hpp"
...
boost::iostreams::stream< boost::iostreams::null_sink > nullOstream( ( boost::iostreams::null_sink() ) );
...
最简单的解决方案就是使用未打开的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()) ? ' ' : c;
}
};
通常提供一个从istream
派生的方便类或ostream
,它将包含this的一个实例它使用的缓冲区。类似以下语句:
class NulOStream : private NulStreambuf, public std::ostream
{
public:
NulOStream() : std::ostream( this ) {}
NulStreambuf* rdbuf() const { return this; }
};
或者您可以直接使用std::ostream
,传递的地址
如果你在流上设置badbit
,它将不会输出任何内容:
#include <iostream>
int main() {
std::cout << "an";
std::cout.setstate(std::ios_base::badbit);
std::cout << "bn";
std::cout.clear();
std::cout << "cn";
}
输出:
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——有一个缺点。如果程序检查输出是否成功写入——我不知道为什么程序不应该这样做——那么它将因为这个错误而失败。因此,亚军boost是获胜者。
根据@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
不需要第三方库也可以做到。只需使用rdbuf
将相关的流缓冲区设置为nullptr
,您的工作就完成了
std::cout << "Hello,";
std::cout.rdbuf(nullptr);
std::cout << " world!n";
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 outputn";
out = nullstream();
*out << "Will not visiblen";
out = &std::cout;
*out << "Back againn";
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){}
};
- boost::interprocess::file_lock 与 std::ostream 一起使用时的错误行为
- 与'operator<<'不匹配(操作数类型'std::ostream {aka std::basic_ostream<char>}'
- 与"operator<<"不匹配(操作数类型'std::ostream'
- 运算符的歧义错误<<自定义 std::ostream 子类中的重载
- 关于 std::ostream 构造函数
- STD :: Ostream忽略了通过setf()在基础上设置的十六进制标志
- 将 std::ostream 转换为 std::string
- STD :: Ostream:类是不可接受的[C ]
- 为什么在三元运算符中使用STD :: Ostream不会编译
- 当我编译引用 std::ostream 时,我有一个奇怪的错误弹出
- 如何跟踪写入std :: Ostream对象的字节数
- std::ostream的下降表达(针对SFINAE)
- BOOST ::变体无法解决运算符&lt;&lt;对于STD :: Ostream
- 我什么时候应该返回 std::ostream
- 如何移动std::ostream
- 如何在自定义 std::ostream 类中使用 std::endl
- 如何清除std::ostream
- 返回对此的引用时出现意外的std::ostream输出
- std::ostream to QDataStream
- 使用 std::ostream 方法将格式化文本输出到 std::string 对象