Ultimamente, tenho feito algumas otimizações necessárias. Uma coisa que venho fazendo é mudar alguns fluxos de ostring -> sprintfs. Estou correndo um monte de std :: strings para uma matriz de estilo ac, ala
char foo[500];
sprintf(foo, "%s+%s", str1.c_str(), str2.c_str());
Acontece que a implementação std :: string :: c_str () da Microsoft é executada em tempo constante (apenas retorna um ponteiro interno). Parece que libstdc ++ faz o mesmo . Sei que o std não garante o c_str, mas é difícil imaginar outra maneira de fazer isso. Se, por exemplo, eles copiassem para a memória, teriam que alocar memória para um buffer (deixando o chamador destruí-lo - NÃO faz parte do contrato STL) OU teriam que copiar para uma estática interna buffer (provavelmente não é seguro para threads e você não tem garantias de vida útil). Portanto, simplesmente retornar um ponteiro para uma sequência terminada nula mantida internamente parece ser a única solução realista.
fonte
c_str
seja um método const (ou pelo menos tenha uma sobrecarga const - eu esqueço qual), isso não altera o valor lógico, portanto pode ser uma razão para issomutable
. Ele iria quebrar ponteiros de outras chamadas parac_str
, a não ser que tais indicações devem referir-se a mesma seqüência lógica (então não há nenhuma nova razão para realocar - já deve ser um terminador nulo) ou então há já deve ter sido uma chamada para um não -const no meio.c_str
chamadas podem ser O (n) hora para a realocação e cópia. Mas também é possível que exista regras extras no padrão que eu desconheço que impediriam isso. A razão que eu sugiro-lo - as chamadasc_str
não são realmente concebido para ser comum AFAIK, por isso não pode ser considerado importante para garantir que eles são rápidos - evitando que byte extra de armazenamento para um terminador nulo normalmente desnecessário emstring
casos que não utilizaçãoc_str
pode tomaram precedência.Boost.Format
internamente passa por fluxos que internamente passam porsprintf
uma sobrecarga bastante grande. A documentação diz que é cerca de 8 vezes mais lento que o normalsprintf
. Se você deseja desempenho e segurança de tipo, tenteBoost.Spirit.Karma
.Boost.Spirit.Karma
é uma boa dica para desempenho, mas tenha em atenção que ela possui uma metodologia muito diferente que pode ser complicada para adaptar oprintf
código de estilo existente (e os codificadores). Eu fiquei bastante presoBoost.Format
porque nossa E / S é assíncrona; mas um grande fator é que posso convencer meus colegas a usá-lo de forma consistente (ainda permite qualquer tipo comostream<<
sobrecarga - o que evita o.c_str()
debate) Os números de desempenho do Karma .No padrão c ++ 11 (estou lendo a versão N 3290), o capítulo 21.4.7.1 fala sobre o método c_str ():
const charT* c_str() const noexcept; const charT* data() const noexcept;
Então, sim: a complexidade do tempo constante é garantida pelo padrão.
Acabei de verificar o padrão c ++ 03, e ele não possui esses requisitos, nem informa a complexidade.
fonte
Em teoria, o C ++ 03 não exige isso e, portanto, a string pode ser uma matriz de caracteres em que a presença do terminador nulo é adicionada exatamente no momento em que c_str () é chamado. Isso pode exigir uma realocação (não viola a constância, se o ponteiro privado interno for declarado como
mutable
).O C ++ 11 é mais rígido: exige custo de tempo, portanto, nenhuma realocação pode ser feita e a matriz sempre deve ser ampla o suficiente para armazenar o nulo no final. c_str (), por si só, ainda pode "
ptr[size()]='\0'
" garantir que o nulo esteja realmente presente. Não viola a constância da matriz, pois o intervalo[0..size())
não é alterado.fonte