istringstream non-copie
-
30-09-2019 - |
Question
copies istringstream
le contenu d'une chaîne quand initialisés, par exemple
string moo("one two three four");
istringstream iss(moo.c_str());
Je me demandais s'il y a un moyen de faire std::istringstream
utiliser la c_str
donnée comme tampon sans copier les choses. De cette façon, il ne sera pas avoir à copier des morceaux de mémoire avant de passer la std::istringstream&
aux fonctions qui prennent istream&
comme argument.
Ce que j'ai essayé de faire est de convertir certaines fonctions qui ne prennent que des arguments std::ifstream&
(ils sont pour la plupart des parseurs) en prenant istream&
aussi bien. Est-ce que je dois faire ma propre sous-classe istream
pour cela?
La solution
Il est assez trivial d'écrire une classe de base std::streambuf
qui lit une zone de mémoire donnée. Vous pouvez ensuite construire un istream
de cela et lire cela.
initialisation d'un C ++ std :: istringstream à partir d'un dans un tampon de mémoire?
Notez que la durée de vie du tampon a être c_str()
est très limitée, cependant, et il n'y a aucune garantie qu'un appel à vouloir de c_str()
la cause une copie bien que je ne connais pas d'implémentations où il fait.
Autres conseils
Utilisation istringstream
est pas une solution satisfaisante, car cette copie le tampon entier.
Une réponse précédente suggère istrstream
désapprouvée, mais cela génère des avertissements et peut être retiré à l'avenir, une meilleure solution consiste à utiliser boost :: iostreams :
boost::iostreams::stream<boost::iostreams::array_source> stream(moo.c_str(), moo.size());
Cette copie la mémoire tampon évite de la même manière istrstream
a fait, et vous évite d'avoir à écrire votre propre classe de flux.
istrstream
désapprouvée supporte cette fonctionnalité.
#include <string>
#include <strstream>
using namespace std;
int main(int argc, char* argv[])
{
string moo = "one two three four";
istrstream istr(const_cast<char*>(moo.c_str()),moo.size());
std::string line;
while(!istr.fail() && !istr.eof()){
getline(istr,line,' ');
cout << line << "_";
}
// prints: one_two_three_four_
}
Il n'y a qu'une copie parce que le paramètre que vous passez, un const char*
, nécessite une conversion au type d'argument de la constructeur istringstream .
Il suffit de passer dans le string
sans appeler c_str()
.
istringstream iss(moo);
Bon ok, cela ne l'empêche pas de copie complètement, mais il élimine une copie inutile. Pour éliminer complètement la copie, vous auriez à réécrire std::stringbuf
, qui précisément évite travaillant directement sur le string
que vous lui donnez.
Cela dépend de ce qu'est un std :: string fait. Selon 27.2.1 / 1 The class basic_istringstream<charT,traits,Allocator> ... uses a basic_stringbuf<charT,traits,Allocator> object to control the associated storage.
Étant donné que la classe doit utiliser un objet, il doit copier construire la chaîne dans cet objet.
La vraie question est pas si une copie stringstream
Le contenu, mais si une chaîne copie construction copiera le contenu ou mettre en œuvre une sorte de système de copie en écriture.