C++ の streambuf を実装し、何も出力しない ostream を作成する2020年06月04日 12時48分48秒

C や C++ で出力をただ単に捨てたいときは、/dev/null を開いた ostream に書き込むことでも、実現できる。デバッグ用の出力などを切替えたりするときに便利だ。しかし、/dev/null とてファイルを開いての呼び出し等が掛かる。そこで、ostream を改造すると、書き出すこと自体を止めて、余計なシステムコールなどを更に削減できる。

C++ のストリーム系の実装はあれこれと絡み合って色々と複雑。ostream を再実装するのはあまり現実的ではない。ostream は streambuf クラスを初期化時に取る。こちら側でバッファの制御をすれば、比較的簡単に実現できる。ostream の関数は仮想関数にはなっていないので、継承しても意味が無いのだ。

streambuf を実装し、ostream 生成時に streambuf を渡せば良い。どうせ組になって使うので、両方継承している。

#include <iostream>

class null_stream : public std::streambuf, public std::ostream
{   
    char buf_[ 128 ];
protected:
    virtual int overflow( int c )
    {   
        std::cout << "overflow( " << c << " )" << std::e
ndl;
        setp( buf_, buf_ + sizeof( buf_ ) );
        return ( c == eof() ? '\0' : c );
    }

public:
    null_stream() : std::ostream( this ) {}
};

int main()
{   
    null_stream stream;
    stream << "HIDDEN MESSAGE" << std::endl;
    std::cout << "HELLO" << std::endl;
    stream << "hidden message" << std::endl;
    std::cout << "hello" << std::endl;
}
overflow 関数がバッファを割り当てるときに呼ばれる。まず最初の出力が最初の割当になる。それ以降は、バッファが足りなくなった時になる。目的と実装によって、sync したり、バッファを広げたり出来る。今回は小さめのバッファを保持し、内容物は無視。

実行結果は以下の通り。overflow 関数が最初に呼び出されたのが分かる。しかし、出力文字列はどこにも行かない。

% c++ null_stream.cpp
% ./a.out 
overflow( 72 )
HELLO
hello

次回

コメント

コメントをどうぞ

※メールアドレスとURLの入力は必須ではありません。 入力されたメールアドレスは記事に反映されず、ブログの管理者のみが参照できます。

※なお、送られたコメントはブログの管理者が確認するまで公開されません。

名前:
メールアドレス:
URL:
コメント:

トラックバック

このエントリのトラックバックURL: http://uyota.asablo.jp/blog/2020/06/04/9254139/tb

※なお、送られたトラックバックはブログの管理者が確認するまで公開されません。