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

pap*_*jam 50 c++ null ostream

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

Jam*_*nze 26

最简单的解决方案就是使用未打开的解决方案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;
    }
};
Run Code Online (Sandbox Code Playgroud)

通常提供一个派生自istream 或来自的便利类ostream,它将包含它使用的这个缓冲区的实例.有点像:

class NulOStream : private NulStreambuf, public std::ostream
{
public:
    NulOStream() : std::ostream( this ) {}
    NulStreambuf* rdbuf() const { return this; }
};
Run Code Online (Sandbox Code Playgroud)

或者你可以使用一个std::ostream,将streambuf的地址传递给它.

  • 最初的想法(未打开的`std :: ofstream`)非常酷.它是否可靠/符合标准,并且不太可能在将来引起问题(例外?)?我有点担心性能,但我想唯一的浪费是`<<`运算符被调用,检查一个`if`并返回? (5认同)

Yli*_*sar 21

如果你有提升,那么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() ) );
...
Run Code Online (Sandbox Code Playgroud)


Max*_*kin 17

如果您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";
}
Run Code Online (Sandbox Code Playgroud)

输出:

a
c
Run Code Online (Sandbox Code Playgroud)

  • @MatthieuM.使用`std :: cout << std :: boolalpha`也是对全局变量的修改.使用`std :: cout << anything`也是.我不明白你的观点. (5认同)
  • @Notinlist:关于`ostream`的设计我有很多*为什么*; 到那时它是早期的C++,其中全局变量仍然是常见的地方并且收集的经验很少,并且它表明......我发现将格式化和输出的位置混淆是很尴尬的,例如,我发现它甚至难以注入*格式化为流而不是使用*Decorator*模式等...但我有后见之明的好处. (2认同)

Grz*_*orz 10

我知道这是一个非常老的线程,但我想将此添加到任何正在寻找相同解决方案而没有提升和最快的解决方案.

我结合了上面的三个不同的提议,一个直接写入/ 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)
Run Code Online (Sandbox Code Playgroud)

这是测试代码

#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;
}
Run Code Online (Sandbox Code Playgroud)

编辑

最快的解决方案 - 我们使用badbit - 有一个缺点.如果程序检查输出是否成功写入 - 并且我不知道为什么程序不应该这样做 - 那么它会因为这个badbit而失败.因此,亚军 - 提升 - 是赢家.


Vla*_*ust 5

按照@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;
}
Run Code Online (Sandbox Code Playgroud)

输出:

a
c
Run Code Online (Sandbox Code Playgroud)