从ostream中获取char *而不进行复制

时间:2014-03-09 03:17:03

标签: c++ char copy buffer ostream

我有一个ostream,并且已经写入了数据。现在我想要char数组形式的数据。有没有办法获取char缓冲区及其大小而不复制所有字节?我的意思是,我知道我可以使用ostringstream并在其上调用str().c_str(),但这会产生临时副本。

1 个答案:

答案 0 :(得分:2)

我想这就是你要找的东西 - 一个流缓冲区,它返回一个指向缓冲区的指针:

#include <iostream>
#include <vector>
#include <string>

class raw_buffer : public std::streambuf
{
public:
    raw_buffer(std::ostream& os, int buf_size = 256);
    int_type overflow(int_type c) override;
    std::streamsize showmanyc() override;
    std::streamsize xsputn(const char_type*, std::streamsize) override; 
    int sync() override;
    bool flush();
    std::string const& str() const;
private:
    std::ostream& os_;
    std::vector<char> buffer;
    std::string aux;
};

现在str()很简单。它返回一个指向辅助缓冲区底层缓冲区的指针:

std::string const& raw_buffer::str() const
{
    return aux;
}

其余的函数是流缓冲区的常用实现。 showmanyc()应该返回辅助缓冲区的大小(aux只是整个缓冲区的运行总和,另一方面buffer是构造时指定的大小。)

例如,这里是overflow(),它应该同时更新两个缓冲区,但仍将buffer视为主缓冲区:

raw_buffer::int_type raw_buffer::overflow(raw_buffer::int_type c) override
{   
    if (os_ && !traits_type::eq_int_type(c, traits_type::eof()))
    {
        aux += *this->pptr() = traits_type::to_char_type(c);
        this->pbump(1);

        if (flush())
        {
            this->pbump(-(this->pptr() - this->pbase()));
            this->setp(this->buffer.data(),
                       this->buffer.data() + this->buffer.size());
            return c;
        } 
    }
    return traits_type::eof();
}

flush()用于将buffer的内容复制到流(os_),并且应覆盖sync()以调用flush()。< / p>

xsputn也需要被覆盖以写入aux

std::streamsize raw_buffer::xsputn(const raw_buffer::char_type* str, std::streamsize count) override
{
    for (int i = 0; i < count; ++i)
    {
        if (traits_type::eq_int_type(this->sputc(str[i]), traits_type::eof()))
            return i;
        else
            aux += str[i];
    }
    return count;
}

现在我们可以将它与自定义流一起放在一起:

class raw_ostream : private virtual raw_buffer
                  , public std::ostream
{
public:
    raw_ostream(std::ostream& os) : raw_buffer(os)
                                  , std::ostream(this)
    { }

    std::string const& str() const
    {
        return this->raw_buffer::str();
    }

    std::streamsize count()
    {
        return this->str().size();
    }
};

可以像这样使用:

int main()
{
    raw_ostream rostr(std::cout);
    rostr << "Hello, World " << 123 << true << false;

    auto& buf = rostr.str();
    std::cout << buf;
}