Estou curioso para saber qual método de cópia é mais eficiente para substrings grandes de MB.
Aqui está um exemplo de programa C++ com muitas maneiras de copiar uma substring de const char*
para std::string
, mas como determinar qual método é mais eficiente? Relacionado a Copiar uma substring de const char* para std::string .
Poderia avaliar todas essas maneiras possíveis, mas talvez falte um método melhor? Talvez existam documentos que indiquem quais evitar imediatamente, pois exigem cópias temporárias ineficientes de dados, etc., ...
#include <iostream>
#include <sstream>
#include <string>
const char* str = "Hello World!";
const char* startOfWorld = str + 6; // Pointing to "World!"
size_t length = 6; // Length of "World!"
void StoreWorldIntoString(std::string& result)
{
result.assign(startOfWorld, length);
// Slower methods...
// result = std::string(startOfWorld, length);
// result.replace(0, result.length(), startOfWorld, length);
// result = std::string(startOfWorld, startOfWorld + length);
// result.append(startOfWorld, length);
// std::string fullString(str); result = fullString.substr(6, length);
// result.insert(0, startOfWorld, length);
// std::copy(startOfWorld, startOfWorld + length, std::back_inserter(result));
// std::stringstream ss; ss.write(startOfWorld, length); result = ss.str();
}
int main()
{
std::string result;
StoreWorldIntoString(result);
std::cout << result << std::endl;
return 0;
}
O vencedor
Com base no benchmarking e nos comentários abaixo, o método mais eficiente é assign
.
Escreva código simples
Usar
result.assign
. Essa é exatamente a função para esta tarefa e, portanto, é praticamente garantido que seja o mais rápido.Quanto mais complexidade você tenta adicionar:
QuickBench nos permite testar isso em detalhes e visualizar a montagem, então vamos fazer isso. https://quick-bench.com/q/5jxTRcmOQ0di2rTDRAyFhUQxGKg . Meus primeiros testes foram apenas para verificar se o último byte foi atribuído, mas muitos testes estavam trapaceando e prejudicando os resultados, então agora verifico o hash de todo o resultado.
assign
,insert
, , e os novos que adicionei são todos mais rápidos e basicamente iguais entre sireplace
. (Na verdade, , e estão simplesmente chamando o mesmo método nos bastidores)append
std::copy(startOfWorld, startOfWorld + length, result.begin())
assign
replace
insert
_M_replace
std::string(startOfWorld, length)
é apenas cerca de 30% mais lento, devido à alocação extra.std::string fullString(str); result = fullString.substr(6, length)
é cerca de 90% mais lento, devido à alocação extra e a uma cópia completa.std::string(startOfWorld, startOfWorld + length)
é cerca de 110% mais lento, o que é surpreendente para mim, devido à alocação e cópia extras. Provavelmente não é estatisticamente mais lento do que a versão anterior e provavelmente foi apenas uma medição infeliz.std::stringstream ss; ss.write(startOfWorld, length)
é ~880% mais lento. streams têm muitas chamadas de métodos virtuais e geralmente é melhor evitá-los, exceto para E/S.std::copy(startOfWorld, startOfWorld + length, std::back_inserter(result))
é impressionante ~ 1100% mais lento. Cada letra está fazendo uma verificação separada para ver se precisa ser redimensionada. É por isso que você normalmente deve usarresize
e depois atribuir diretamente (o que mostro nostd::copy(startOfWorld, startOfWorld + length, result.begin())
teste que adicionei)