Existe uma classe C ++ Standard Template Library que fornece funcionalidade eficiente de concatenação de cadeias, semelhante ao StringBuilder do C # ou ao StringBuffer do Java ?
c++
stl
string-concatenation
An̲̳̳drew
fonte
fonte
std::ostringstream
.Respostas:
NOTA esta resposta recebeu alguma atenção recentemente. Não estou defendendo isso como uma solução (é uma solução que eu já vi no passado, antes do STL). É uma abordagem interessante e só deve ser aplicada sobre
std::string
oustd::stringstream
se, após criar um perfil do seu código, você descobrir que isso melhora.Eu normalmente uso um
std::string
oustd::stringstream
. Eu nunca tive problemas com isso. Normalmente, eu reservaria um espaço primeiro se soubesse o tamanho aproximado da corda com antecedência.Vi outras pessoas criarem seu próprio construtor de strings otimizado no passado distante.
Ele usa duas strings, uma para a maioria das strings e a outra como uma área de rascunho para concatenar strings curtas. Ele otimiza os anexos agrupando em lotes as operações de acréscimo curto em uma cadeia pequena e, em seguida, anexando-a à cadeia principal, reduzindo assim o número de realocações necessárias na cadeia principal à medida que ela aumenta.
Eu não exigi esse truque com
std::string
oustd::stringstream
. Eu acho que foi usado com uma biblioteca de strings de terceiros antes de std :: string, foi há muito tempo. Se você adotar uma estratégia como esse perfil, seu aplicativo primeiro.fonte
scratch
corda realmente realiza alguma coisa aqui. O número de realocações da cadeia principal será em grande parte uma função de seu tamanho final, não o número de operações de acréscimo, a menos que astring
implementação seja realmente ruim (ou seja, não use crescimento exponencial). Portanto, "agrupar" oappend
pacote não ajuda, porque, uma vez que o subjacentestring
é grande, ele só cresce ocasionalmente de qualquer maneira. Além disso, ele adiciona várias operações de cópia redundante e pode ter mais realocações (daí chamadas paranew
/delete
), pois você está anexando uma sequência curta.str.reserve(1024);
seria mais rápido do que essa coisaA maneira C ++ seria usar std :: stringstream ou concatenações de strings simples. As seqüências de caracteres C ++ são mutáveis; portanto, as considerações de desempenho da concatenação são menos preocupantes.
no que diz respeito à formatação, você pode fazer a mesma formatação em um fluxo, mas de uma maneira diferente, semelhante a
cout
. ou você pode usar um functor fortemente tipado que encapsula isso e fornece uma String.Format como interface, por exemplo, boost :: formatfonte
StringBuilder
existe é para cobrir a ineficiência do tipo String imutável básico do Java . Em outras palavras,StringBuilder
é uma colcha de retalhos; portanto, devemos estar felizes por não precisarmos dessa classe em C ++.O(n)
em geral.A
std::string.append
função não é uma boa opção porque não aceita muitas formas de dados. Uma alternativa mais útil é usarstd::stringstream
; igual a:fonte
std::string
é o equivalente em C ++: é mutável.fonte
Você pode usar .append () para simplesmente concatenar seqüências de caracteres.
Eu acho que você pode até fazer:
Quanto às operações de formatação dos C #
StringBuilder
, acreditosnprintf
(ousprintf
se você quiser arriscar escrever código de buggy ;-)) em uma matriz de caracteres e converter novamente em uma string é a única opção.fonte
Como
std::string
no C ++ é mutável, você pode usá-lo. Tem+= operator
umaappend
função e.Se você precisar acrescentar dados numéricos, use as
std::to_string
funções.Se você deseja ainda mais flexibilidade na forma de poder serializar qualquer objeto em uma string, use a
std::stringstream
classe Mas você precisará implementar suas próprias funções de operador de streaming para que ele funcione com suas próprias classes personalizadas.fonte
std :: string + = não funciona com const char * (o que parece ser "string a adicionar"), então definitivamente usar stringstream é o mais próximo do que é necessário - basta usar << em vez de +
fonte
Um construtor de strings conveniente para c ++
Como muitas pessoas responderam antes, std :: stringstream é o método de escolha. Funciona bem e possui muitas opções de conversão e formatação. IMO, porém, tem uma falha bastante inconveniente: você não pode usá-lo como um liner ou como uma expressão. Você sempre tem que escrever:
o que é bastante irritante, especialmente quando você deseja inicializar seqüências de caracteres no construtor.
O motivo é que a) std :: stringstream não tem operador de conversão para std :: string eb) os operadores << () do stringstream não retornam uma referência stringstream, mas uma referência std :: ostream - que não pode mais ser computado como um fluxo de strings.
A solução é substituir o std :: stringstream e oferecer melhores operadores correspondentes:
Com isso, você pode escrever coisas como
mesmo no construtor.
Tenho que confessar que não medi o desempenho, pois ainda não o usei em um ambiente que faça uso pesado da construção de strings, mas presumo que não será muito pior do que std :: stringstream, pois tudo está feito via referências (exceto a conversão em string, mas isso também é uma operação de cópia em std :: stringstream)
fonte
std::stringstream
que não se comporta dessa maneira.O contêiner Rope pode valer a pena se for necessário inserir / excluir uma string no local aleatório da string de destino ou por longas sequências de caracteres. Aqui está um exemplo da implementação da SGI:
fonte
Eu queria adicionar algo novo por causa do seguinte:
Numa primeira tentativa, não consegui vencer
std::ostringstream
éoperator<<
eficiência, mas com mais tentativas, consegui criar um StringBuilder que é mais rápido em alguns casos.
Sempre que anexo uma string, apenas guardo uma referência a ela em algum lugar e aumento o contador do tamanho total.
A maneira real de finalmente implementá-lo (Horror!) É usar um buffer opaco (std :: vector <char>):
para byte []
para cadeias movidas (cadeias anexadas com
std::move
)std::string
objeto (temos propriedade)para cordas
std::string
objeto (sem propriedade)Há também uma pequena otimização: se a última string inserida foi movida, ela verifica se há bytes reservados reservados, mas não utilizados, livres e armazena mais bytes lá em vez de usar o buffer opaco (isso é para economizar memória, na verdade, fica um pouco mais lento , talvez dependa também da CPU, e é raro ver sequências com espaço reservado extra de qualquer maneira)
Finalmente, isso foi um pouco mais rápido do que,
std::ostringstream
mas tem poucas desvantagens:ostringstream
conclusão? usar
std::ostringstream
Ele já corrige o maior gargalo, enquanto ganhar alguns pontos percentuais em velocidade com a implementação da mina não vale a pena.
fonte