C ++或库中是否存在null std :: ostream实现?

时间:2011-11-23 14:22:30

标签: c++ null ostream

我正在寻找像std::ostream一样的/dev/null实现。它会忽略流向它的任何内容。标准库或Boost中是否存在这样的事情?或者我必须自己滚动?

9 个答案:

答案 0 :(得分:22)

最简单的解决方案就是使用未打开的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派生的便利类 或ostream也将包含此实例 它使用的缓冲区。有点像:

class NulOStream : private NulStreambuf, public std::ostream
{
public:
    NulOStream() : std::ostream( this ) {}
    NulStreambuf* rdbuf() const { return this; }
};

或者你可以使用std::ostream,传递地址 streambuf到它。

答案 1 :(得分:19)

如果你有提升,那么就有一个空的ostream& boost / iostreams / device / null.hpp中提供了istream实现。它的要点:

#include "boost/iostreams/stream.hpp"
#include "boost/iostreams/device/null.hpp"
...
boost::iostreams::stream< boost::iostreams::null_sink > nullOstream( ( boost::iostreams::null_sink() ) );
...

答案 2 :(得分:15)

如果您在流上设置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

答案 3 :(得分:6)

我知道这是一个非常古老的主题,但我想将此添加到任何正在寻找相同解决方案但没有提升且速度最快的人。

我结合了上面的三个不同的提议,一个直接写入/ 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 - 有一个缺点。如果程序检查输出是否成功写入 - 并且我不知道为什么程序不应该这样做 - 那么它会因为这个badbit而失败。 因此,亚军 - 提升 - 是赢家。

答案 4 :(得分:4)

根据@ 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

答案 5 :(得分:2)

您可以在没有第三方库的情况下进行操作。只需使用rdbuf将关联的流缓冲区设置为nullptr,即可完成工作

std::cout << "Hello,";
std::cout.rdbuf(nullptr);
std::cout << " world!\n";

在线示例here

答案 6 :(得分:1)

对我来说,最简单的方法是:

#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;
}

答案 7 :(得分:0)

此解决方案可以在不使用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){}
};

答案 8 :(得分:0)

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