Je ne m'en soucierais pas. Si vous le faites en boucle, les chaînes préalloueront toujours la mémoire pour minimiser les réallocations - utilisez simplement operator+=
dans ce cas. Et si vous le faites manuellement, quelque chose comme ça ou plus
a + " : " + c
Ensuite, il crée des temporaires - même si le compilateur peut éliminer certaines copies de valeur de retour. En effet, dans un appel successivement, operator+
il ne sait pas si le paramètre de référence fait référence à un objet nommé ou à un temporaire renvoyé par un sous- operator+
appel. Je préfère ne pas m'en soucier avant de ne pas avoir profilé au préalable. Mais prenons un exemple pour le montrer. Nous introduisons d'abord des parenthèses pour rendre la liaison claire. Je mets les arguments directement après la déclaration de fonction utilisée pour plus de clarté. En dessous, je montre quelle est alors l'expression résultante:
((a + " : ") + c)
calls string operator+(string const&, char const*)(a, " : ")
=> (tmp1 + c)
Maintenant, dans cet ajout, tmp1
est ce qui a été renvoyé par le premier appel à operator + avec les arguments affichés. Nous supposons que le compilateur est vraiment intelligent et optimise la copie de la valeur de retour. Nous nous retrouvons donc avec une nouvelle chaîne contenant la concaténation de a
et " : "
. Maintenant, cela se produit:
(tmp1 + c)
calls string operator+(string const&, string const&)(tmp1, c)
=> tmp2 == <end result>
Comparez cela à ce qui suit:
std::string f = "hello";
(f + c)
calls string operator+(string const&, string const&)(f, c)
=> tmp1 == <end result>
Il utilise la même fonction pour un temporaire et pour une chaîne nommée! Le compilateur doit donc copier l'argument dans une nouvelle chaîne et l'ajouter à cela et le renvoyer à partir du corps de operator+
. Il ne peut pas prendre la mémoire d'un temporaire et y ajouter. Plus l'expression est grande, plus il faut faire de copies de chaînes.
Ensuite, Visual Studio et GCC prendront en charge la sémantique de déplacement de c ++ 1x (complétant la sémantique de copie ) et les références rvalue comme ajout expérimental. Cela permet de savoir si le paramètre fait référence à un temporaire ou non. Cela rendra ces ajouts incroyablement rapides, car tout ce qui précède se terminera dans un "add-pipeline" sans copies.
Si cela s'avère être un goulot d'étranglement, vous pouvez toujours le faire
std::string(a).append(" : ").append(c) ...
Les append
appels ajoutent l'argument à *this
, puis renvoient une référence à eux-mêmes. Il n'y a donc pas de copie des temporaires. Ou bien, le operator+=
peut être utilisé, mais vous auriez besoin de parenthèses laides pour fixer la priorité.