J'ai déjà essayé plusieurs choses,
std::stringstream m;
m.empty();
m.clear();
qui ne fonctionnent pas.
J'ai déjà essayé plusieurs choses,
std::stringstream m;
m.empty();
m.clear();
qui ne fonctionnent pas.
Pour tous les types de bibliothèque standard, la fonction membre empty()
est une requête, pas une commande, c'est-à-dire que cela signifie "êtes-vous vide ?" et non "veuillez jeter votre contenu".
La fonction membre clear()
est héritée de ios
et est utilisée pour effacer l'état d'erreur du flux, par exemple si un flux de fichier a l'état d'erreur défini sur eofbit
(fin de fichier), alors appeler clear()
rétablira l'état d'erreur à goodbit
(pas d'erreur).
Pour effacer le contenu d'un stringstream
, utiliser :
m.str("");
est correct, bien que l'utilisation de :
m.str(std::string());
soit techniquement plus efficace, car vous évitez d'invoquer le constructeur std::string
prenant const char*
. Mais tout compilateur de nos jours devrait être capable de générer le même code dans les deux cas - donc je choisirais simplement ce qui est le plus lisible.
Voici ce qui se passe lorsque vous oubliez la partie "clear()". stackoverflow.com/q/2848087/635549
@KshitijBanerjee Je pense qu'en C++ m.str() et m.str("") sont deux fonctions différentes. m.str() invoque une fonction qui n'attendait aucun paramètre alors que m.str("") invoquera la fonction qui accepte un paramètre const char*. m.str() pourrait avoir été implémenté comme une fonction get qui renvoie la chaîne de caractères alors que m.str("") pourrait avoir été implémenté comme une fonction set.
Vous pouvez effacer l'état d'erreur et vider le stringstream en une seule ligne
std::stringstream().swap(m); // échanger m avec un stringstream construit par défaut
Cela réinitialise efficacement m à un état construit par défaut, ce qui signifie que cela supprime en réalité les tampons alloués par le stringstream et réinitialise l'état d'erreur. Voici une preuve expérimentale :
int main ()
{
std::string payload(16, 'x');
std::stringstream *ss = new std::stringstream; // Crée une fuite de mémoire
(*ss) << payload; // Fuite de mémoire supplémentaire
// Maintenant choisissez une manière de "vider" un stringstream
//std::stringstream().swap(*ss); // Méthode 1
//ss->str(std::string()); // Méthode 2
std::cout << "fin" << std::endl;
}
Lorsque la démonstration est compilée avec un vérificateur d'adresse, l'utilisation de la mémoire est révélée :
=================================================================
==10415==ERROR: LeakSanitizer: detected memory leaks
Fuite directe de 392 octet(s) dans 1 objet(s) alloué(s) provenant de :
#0 0x510ae8 in operator new(unsigned long) (/tmp/1637178326.0089633/a.out+0x510ae8)
#1 0x514e80 in main (/tmp/1637178326.0089633/a.out+0x514e80)
#2 0x7f3079ffb82f in __libc_start_main /build/glibc-Cl5G7W/glibc-2.23/csu/../csu/libc-start.c:291
Fuite indirecte de 513 octet(s) dans 1 objet(s) alloué(s) provenant de :
#0 0x510ae8 in operator new(unsigned long) (/tmp/1637178326.0089633/a.out+0x510ae8)
#1 0x7f307b03a25c in std::__cxx11::basic_string, std::allocator >::reserve(unsigned long) (/usr/local/lib64/libstdc++.so.6+0x13725c)
#2 0x603000000010 ()
RÉSUMÉ: AddressSanitizer: 905 octet(s) fuit(s) dans 2 allocation(s).
Assez raide si vous me demandez. Pour contenir seulement 16 octets de charge utile, nous avons dépensé 905 octets ... les stringstream ne sont pas un jouet. La mémoire est allouée en deux parties :
Si vous activez la méthode 1 (celle indiquée dans cette réponse), les 513 octets supplémentaires (charge utile) sont récupérés, car le stringstream est effectivement effacé.
Si vous activez la méthode 2 comme suggéré dans les commentaires ou d'autres réponses, vous pouvez voir que les 905 octets sont tous utilisés au moment où nous quittons.
En termes de sémantique du programme, on peut simplement se soucier du fait que le stringstream "paraît" et "se comporte" comme vide, de manière similaire à la façon dont un vector::clear
peut laisser la capacité inchangée mais rendre le vecteur vide pour l'utilisateur (bien sûr, le vecteur ne dépenserait que 16 octets ici). Étant donné l'allocation de mémoire requise par le stringstream, je peux imaginer que cette approche est souvent plus rapide. L'objectif principal de cette réponse est en fait d'effacer le stringstream, étant donné que la consommation de mémoire qui l'accompagne n'est pas une plaisanterie. Selon votre cas d'utilisation (nombre de stringstream, données qu'ils contiennent, fréquence de l'effacement), vous pouvez choisir la meilleure approche.
Enfin, notez qu'il est rarement utile d'effacer le stringstream sans effacer l'état d'erreur et tout l'état hérité. La ligne unique dans cette réponse fait les deux.
Ceci est la manière la plus efficace et la plus élégante de le faire par rapport à toutes les autres réponses ici. Cependant, std :: stringstream :: swap est une fonctionnalité c ++ 11 et cette solution ne fonctionne pas pour les compilateurs c ++ 11 antérieurs.
Fonctionnalité toujours manquante dans GNU g++ v4.8, consultez stackoverflow.com/questions/24429441/…
Ceci est meilleur à mon avis car m.str(""); a causé mon stringstream à rester coincé avec cette valeur vide quoi que j'essaie. Mais en utilisant cela, je n'ai pas ce problème.
Je suis tombé sur le même problème, pour moi mm.clear(); mm.str("");
a fonctionné. (pas de C++11, sinon swap serait meilleur).
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.