Non me ne preoccuperei. Se lo fai in un ciclo, le stringhe preallocheranno sempre la memoria per ridurre al minimo le riallocazioni, basta usarle operator+=
in quel caso. E se lo fai manualmente, qualcosa di simile o più lungo
a + " : " + c
Quindi crea dei provvisori, anche se il compilatore potrebbe eliminare alcune copie del valore di ritorno. Questo perché in un richiamo successivo operator+
non sa se il parametro di riferimento fa riferimento a un oggetto denominato oa un temporaneo restituito da una sottovocazione operator+
. Preferirei non preoccuparmene prima di non aver prima profilato. Ma facciamo un esempio per dimostrarlo. Per prima cosa introduciamo le parentesi per rendere chiara la rilegatura. Metto gli argomenti direttamente dopo la dichiarazione di funzione utilizzata per chiarezza. Di seguito, mostro qual è l'espressione risultante:
((a + " : ") + c)
calls string operator+(string const&, char const*)(a, " : ")
=> (tmp1 + c)
Ora, in aggiunta, tmp1
è ciò che è stato restituito dalla prima chiamata all'operatore + con gli argomenti mostrati. Supponiamo che il compilatore sia davvero intelligente e ottimizzi la copia del valore restituito. Quindi finiamo con una nuova stringa che contiene la concatenazione di a
e " : "
. Ora, questo accade:
(tmp1 + c)
calls string operator+(string const&, string const&)(tmp1, c)
=> tmp2 == <end result>
Confrontalo con quanto segue:
std::string f = "hello";
(f + c)
calls string operator+(string const&, string const&)(f, c)
=> tmp1 == <end result>
Usa la stessa funzione per una stringa temporanea e per una stringa con nome! Quindi il compilatore deve copiare l'argomento in una nuova stringa e aggiungervi e restituirlo dal corpo di operator+
. Non si può prendere il ricordo di un temporaneo e aggiungerlo a quello. Più grande è l'espressione, più copie di stringhe devono essere eseguite.
Successivamente Visual Studio e GCC supporteranno la semantica di spostamento di c ++ 1x (complementare alla semantica di copia ) e i riferimenti rvalue come aggiunta sperimentale. Ciò consente di capire se il parametro fa riferimento a un temporaneo o meno. Ciò renderà tali aggiunte incredibilmente veloci, poiché tutto quanto sopra finirà in una "pipeline di aggiunta" senza copie.
Se risulta essere un collo di bottiglia, puoi comunque farlo
std::string(a).append(" : ").append(c) ...
Le append
chiamate aggiungono l'argomento a *this
e quindi restituiscono un riferimento a se stesse. Quindi nessuna copia dei provvisori viene eseguita lì. O in alternativa, operator+=
può essere utilizzato, ma per correggere la precedenza sarebbero necessarie brutte parentesi.