Eu não me preocuparia com isso. Se você fizer isso em um loop, as strings sempre pré-alocarão a memória para minimizar as realocações - apenas use operator+=
nesse caso. E se você fizer manualmente, algo assim ou mais
a + " : " + c
Então está criando temporários - mesmo se o compilador pudesse eliminar algumas cópias de valor de retorno. Isso ocorre porque em um chamado sucessivamente, operator+
ele não sabe se o parâmetro de referência faz referência a um objeto nomeado ou a um temporário retornado de uma sub operator+
invocação. Prefiro não me preocupar com isso antes de não ter feito o perfil primeiro. Mas vamos dar um exemplo para mostrar isso. Primeiro, introduzimos parênteses para tornar a ligação clara. Eu coloco os argumentos diretamente após a declaração da função que é usada para maior clareza. Abaixo disso, mostro qual é a expressão resultante:
((a + " : ") + c)
calls string operator+(string const&, char const*)(a, " : ")
=> (tmp1 + c)
Agora, nessa adição, tmp1
é o que foi retornado pela primeira chamada ao operador + com os argumentos mostrados. Assumimos que o compilador é realmente inteligente e otimiza a cópia do valor de retorno. Portanto, terminamos com uma nova string que contém a concatenação de a
e " : "
. Agora, isso acontece:
(tmp1 + c)
calls string operator+(string const&, string const&)(tmp1, c)
=> tmp2 == <end result>
Compare isso com o seguinte:
std::string f = "hello";
(f + c)
calls string operator+(string const&, string const&)(f, c)
=> tmp1 == <end result>
Ele está usando a mesma função para uma string temporária e para uma string nomeada! Portanto, o compilador precisa copiar o argumento em uma nova string e anexar a ela e retorná-la do corpo de operator+
. Não pode tirar a memória de um temporário e anexar a isso. Quanto maior a expressão, mais cópias de strings precisam ser feitas.
Em seguida, o Visual Studio e o GCC oferecerão suporte à semântica de movimentação de c ++ 1x (complementando a semântica de cópia ) e referências rvalue como uma adição experimental. Isso permite descobrir se o parâmetro faz referência a um temporário ou não. Isso tornará essas adições incrivelmente rápidas, já que todos os itens acima acabarão em um "add-pipeline" sem cópias.
Se for um gargalo, você ainda pode
std::string(a).append(" : ").append(c) ...
As append
chamadas acrescentam o argumento a *this
e, em seguida, retornam uma referência a si mesmas. Portanto, nenhuma cópia de temporários é feita lá. Ou, alternativamente, o operator+=
pode ser usado, mas você precisaria de parênteses feios para fixar a precedência.