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?

Était-ce utile?

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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top