Pergunta

Estou tentando implementar um buffer de fluxo e estou tendo problemas para fazer overflow() trabalhar. Eu redimensiono o buffer por mais 10 caracteres e redefinindo o buffer usando setp. Então eu incremento o ponteiro para trás de onde paramos. Por alguma razão, a saída não está certa:

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();
}

Quando imprimir a string, ela sai como:

Olá worl, como estão você?

Está faltando o d e a y. O que eu fiz errado?

Foi útil?

Solução

A primeira coisa a não ser que você está derivando std::basic_stringbuf<char> por qualquer motivo, sem substituir todas as funções virtuais relevantes. Por exemplo, você não substitui xsputn() ou sync(): Quaisquer que sejam essas funções, você herdará. Eu recomendo fortemente derivar seu buffer de fluxo de std::basic_streambuf<char> em vez de!

o overflow() O método anuncia um buffer que é um caractere menor que a corda do buffer de fluxo: &buffer.back() Não é um ponteiro para o final da matriz, mas para o último personagem na string. Pessoalmente, eu usaria

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

Até agora, não há problema. No entanto, depois de abrir espaço para mais personagens que você omitiu adicionando o personagem transbordante, ou seja, o argumento passou para overflow() para o buffer:

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

Existem mais algumas pequenas coisas que não estão certas:

  1. Geralmente é uma má ideia dar a substituição virtual Funções Um parâmetro padrão. A função de classe base já fornece o padrão e o novo padrão é retirado apenas quando a função é sempre chamada explicitamente.
  2. A string retornada pode conter vários caracteres nulos no final, porque a string mantida é realmente maior que a sequência que foi escrita até agora, a menos que o buffer esteja exatamente cheio. Você provavelmente deve implementar o str() função de maneira diferente:

    std::basic_string<charT> str() const
    {
        return this->buffer.substr(0, this->pptr() - this->pbase());
    }
    
  3. O crescimento da corda por um valor constante é um grande problema de desempenho: o custo de escrita n Os personagens são n * n. Para maior n (Eles realmente não precisam se tornar enormes) Isso causará problemas. Você está muito melhor crescendo seu buffer exponencialmente, por exemplo, dobrando -o toda vez ou crescendo por um fator de 1.5 Se você sente dobrar, não é uma boa ideia.
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top