OVH Cloud OVH Cloud

Equivalent StringBuilder

17 réponses
Avatar
Delf
Bonsoir,

je cherche un équivalent de StringBuffer/StringBuilder mais en C++.

J'ai une chaîne que je créé par concaténation de nombreux caractères...
pas très performant...

Merci :)

--
Delf
Do not use this email in Cc!
Quand je vais aux chiottes, je prends un manuel CISCO.

7 réponses

1 2
Avatar
Delf
Fabien LE LEZ wrote:

Et pourquoi réallouerais-tu à chaque concaténation ?
Note que si tu utilises reserve() à bon escient, tu es assuré de
l'absence de réallocation.
[...]
Crée puis compile le programme, et fais-le tourner.
S'il tourne assez vite, ton boulot est terminé.
[...]
S'il est trop lent, il te faut un profiler pour déterminer la cause de
cette lenteur. Elle n'est pas forcément où tu l'attends.


Ce que je vais faire pour l'instant, c'est garder le code actuel, et je
verrai comment tout ça se comporte lors d'une exécution normale.

Pour l'instant, je ne peux pas le faire tourner, il me faut certaines
données en entrée que je n'ai pas.

Merci.

--
Delf
Do not use this email in Cc!
A quoi bon soulever des montagnes quand il est si simple de passer par
dessus ?

Avatar
Fabien LE LEZ
On Sun, 30 Apr 2006 12:49:56 +0200, James Kanze :

suivi d'un std::string( v.begin(), v.end() ) pour
convertir le résultat en chaîne.


Attention, je connais au moins un compilateur[*] (ou plutôt la SL qui
va avec) où ça ne marche pas : si mes souvenirs sont bons, ce con-là
fait un std::string::push_back() par élément :-(
Par contre, std::string (&v[0], v.size()) fonctionne.


[*] Borland C++ 5.02. Mais t'es trop jeune pour l'avoir connu...

Avatar
James Kanze
Delf wrote:
Fabien LE LEZ wrote:


Tu veux dire que tu as effectivement vérifié que std::string
est trop lent pour tes besoins ?



Non. Mais si je réalloue à chaque concaténation, je suis
persuadé que c'est pas le mieux à faire.


Le fait que string a à la fois une capacité et une taille laisse
penser que l'intention est qu'il n'alloue pas à chaque
concatenation.

Si oui, et si tu as une estimation de la taille finale, tu
peux commencer par essayer en utilisant
std::string::reserve().



J'avais pensé à utiliser reverse() mais je ne peux pas estimer
la taille finale.


Tu pourrais toujours t'en servir pour forcer une stratégie de
croissance à ta guise.

--
James Kanze
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34


Avatar
James Kanze
Delf wrote:
Fabien LE LEZ wrote:


Pour rajouter des caractères, j'ai des doutes. Utiliser
directement std::string::append() n'est-il pas plus efficace
?



A vrai dire, je ne sais pas. En Java ou C#, quand je concatène
des caractères, je n'utilise jamais la classe String mais son
équivalent.


La conception de java.lang.String est bien différent de celle de
std::string. En Java, String est immuable -- pour y ajouter un
caractère, il faut faire quelque chose du genre :
s = s + caractère ;
où « s + caractère » est une forme simplifiée d'écrire :
new StringBuffer( s ).append( charactère ).asString() ;
Et oui, pour créer une chaîne caractère par caractère, ça risque
d'être un peu lent. En C++, en revanche, std::string n'est pas
du tout immuable, et il n'y a pas de raison de croire a priori
que « s += caractère » fasse la moindre allocation. (De temps en
temps, il en faudra bien, mais pas à chaque coup.)

Après, je n'ai jamais fait de tests de performance, je fais
confiance aux documentations.


Sauf que les documentations ne disent jamais si une telle
fonctionnalité va poser un problème de performance dans ton
application. Il y a des cas (beaucoup même) en Java où
j'écrivais « s = s + caractère ». Et mes applications étaient
assez vites quand même.

--
James Kanze
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34


Avatar
James Kanze
Fabien LE LEZ wrote:
On Sun, 30 Apr 2006 12:49:56 +0200, James Kanze :


suivi d'un std::string( v.begin(), v.end() ) pour
convertir le résultat en chaîne.



Attention, je connais au moins un compilateur[*] (ou plutôt la
SL qui va avec) où ça ne marche pas : si mes souvenirs sont
bons, ce con-là fait un std::string::push_back() par élément
:-(


Intéressant. C'est vrai qu'à l'encontre de std::vector, la norme
n'impose rien en ce qui concerne les performances, mais vue
qu'on est obligé à implémenter la logique dans std::vector,
c'est un peu bête de ne pas se servir de la même logique dans
std::basic_string.

Note aussi que dans la passée, il y a eu beaucoup de
compilateurs qui ne supportaient même pas du tout ce
constructeur (qui a besoin des template membre) -- VC++ 6.0 en
était un, et c'est un compilateur encore assez répendu.

Par contre, std::string (&v[0], v.size()) fonctionne.


Bon tuyau -- c'est en effet quasiment garanti, et ça doit
marcher même avec les compilateurs des plus anciens.

[*] Borland C++ 5.02. Mais t'es trop jeune pour l'avoir
connu...


Jamais connu, en effet:-).

--
James Kanze
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34


Avatar
Sylvain
James Kanze wrote on 30/04/2006 23:01:
Delf wrote:

A vrai dire, je ne sais pas. En Java ou C#, quand je concatène
des caractères, je n'utilise jamais la classe String mais son
équivalent.


La conception de java.lang.String est bien différent de celle de
std::string. En Java, String est immuable -- pour y ajouter un
caractère, il faut faire quelque chose du genre :


par "son équivalent", je pense que Delf indiquait qu'il cherchait un
"CppStringBuffer" équivalent à java.lang.StringBuffer qu'il utilise en
lieu et place de java.lang.String lorsqu'il concatène des chars.

le fait est qu'en effet std::string tient lieu à la fois de de String et
de StringBuffer, reste que l'expandCapacity de Sun peut être codé
facilement dans une classe originale, comme il figure
(fonctionnellement) surement déjà dans std::string.

Sylvain.


Avatar
James Kanze
Sylvain wrote:
James Kanze wrote on 30/04/2006 23:01:
Delf wrote:



A vrai dire, je ne sais pas. En Java ou C#, quand je concatène des
caractères, je n'utilise jamais la classe String mais son
équivalent.




La conception de java.lang.String est bien différent de celle de
std::string. En Java, String est immuable -- pour y ajouter un
caractère, il faut faire quelque chose du genre :



par "son équivalent", je pense que Delf indiquait qu'il
cherchait un "CppStringBuffer" équivalent à
java.lang.StringBuffer qu'il utilise en lieu et place de
java.lang.String lorsqu'il concatène des chars.


Certes. Moi, j'ai simplement expliqué pourquoi on n'a pas une
telle classe en C++.

le fait est qu'en effet std::string tient lieu à la fois de de
String et de StringBuffer, reste que l'expandCapacity de Sun
peut être codé facilement dans une classe originale, comme il
figure (fonctionnellement) surement déjà dans std::string.


Quel « expandCapacity » ? Si tu parles de
StringBuffer.ensureCapacity, la fonction équivalent fait déjà
partie de std::string, sous le nom de capacité.

La conception de std::string n'est pas la seule possible ; ma
classe pré-norme String, par exemple, se comporter bien plus
comme java.lang.String que comme std::string, et j'avais bien
une deuxième classe, StringBuilder, qui ressemblait beaucoup à
java.lang.StringBuffer. (Le tout, bien avant que Java n'ait vu
le jours.)

--
James Kanze
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34



1 2