我正在尝试实施流缓冲区,并且在制作方面遇到麻烦 overflow() 工作。我通过10个字符调整缓冲区大小,然后使用 setp. 。然后,我将指针汇回我们离开的地方。由于某种原因,输出不正确:

template <class charT, class traits = std::char_traits<charT>>
class stringbuf : public std::basic_stringbuf<charT, traits>
{
public:
    using char_type   = charT;
    using traits_type = traits;
    using int_type    = typename traits::int_type;
public:
    stringbuf()
        : buffer(10, 0)
    {
        this->setp(&buffer.front(), &buffer.back());
    }

    int_type overflow(int_type c = traits::eof())
    {
        if (traits::eq_int_type(c, traits::eof()))
            return traits::not_eof(c);

        std::ptrdiff_t diff = this->pptr() - this->pbase();

        buffer.resize(buffer.size() + 10);
        this->setp(&buffer.front(), &buffer.back());

        this->pbump(diff);

        return traits::not_eof(traits::to_int_type(*this->pptr()));
    }
    // ...
    std::basic_string<charT> str()
    {
        return buffer;
    }
private:
    std::basic_string<charT> buffer;
};

int main()
{
    stringbuf<char> buf;
    std::ostream os(&buf);

    os << "hello world how are you?";
    std::cout << buf.str();
}

当我打印字符串时,它出现为:

你好,沃尔怎么样?

缺少 dy. 。我做错了什么?

有帮助吗?

解决方案

首先要的是你是从 std::basic_stringbuf<char> 无论出于何种原因,都不覆盖所有相关的虚拟功能。例如,您不覆盖 xsputn() 或者 sync(): :无论这些功能最终都可以继承。我强烈建议您从 std::basic_streambuf<char> 反而!

overflow() 方法宣布一个缓冲区,该缓冲区比流缓冲区小的字符串小: &buffer.back() 不是指向数组末尾的指针,而是字符串中的最后一个字符。就我个人而言,我会使用

this->setp(&this->buffer.front(), &this->buffer.front() + this->buffer.size());

到目前为止没有问题。但是,在为更多字符腾出空间后,您省略了添加溢出的字符,即,参数传递给了 overflow() 到缓冲区:

this->pbump(diff);
*this->pptr() = traits::to_char_type(c);
this->pbump(1);

还有一些不太正确的小东西:

  1. 通常是一个坏主意 virtual 函数默认参数。基类函数已经提供默认值,只有在曾经明确调用该函数时才能挑选新的默认值。
  2. 返回的字符串在末尾可能包含许多空字符,因为固定字符串实际上比序列大于到目前为止,除非缓冲区完全满。您可能应该实施 str() 功能不同:

    std::basic_string<charT> str() const
    {
        return this->buffer.substr(0, this->pptr() - this->pbase());
    }
    
  3. 通过恒定值种植字符串是一个主要的性能问题:写作成本 n 字符是 n * n. 。对于较大 n (他们真的不需要变得庞大)这会引起问题。您会更好地成长 buffer 呈指数级,例如,每次将其加倍或增加一倍 1.5 如果您觉得加倍不是一个好主意。
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top