2010-06-26 5 views
7

Así istringstream copia el contenido de una cadena cuando se inicializa, por ejemplono copiar istringstream

string moo("one two three four"); 
istringstream iss(moo.c_str()); 

Me preguntaba si hay una manera de hacer uso del std::istringstreamc_str dado como su búfer sin copiar cosas. De esta forma, no tendrá que copiar grandes bits de memoria antes de pasar el std::istringstream& a funciones que toman istream& como argumento.

Lo que he estado tratando de hacer es convertir algunas funciones que solo toman std::ifstream& argumentos (son en su mayoría analizadores) en tomar istream& también. ¿Tendría que hacer mi propia subclase istream para esto?

+0

Ver [esta respuesta] (http: // stackoverflow.com/questions/2786816/how-to-create-c-istringstream-from-a-char-array-with-null0-characters/2786872 # 2786872) para una forma de hacerlo (básicamente idéntica a la solución de @ Charles, pero envolviendo un 'istream' a su alrededor por conveniencia). –

Respuesta

3

Es bastante trivial para escribir una clase básica std::streambuf que lee de una zona de memoria determinada. A continuación, puede construir un istream de esto y leer de eso.

initializing a C++ std::istringstream from an in memory buffer?

Tenga en cuenta que la vida útil del buffer apuntado para ser c_str() es muy limitado, sin embargo, y no hay garantía de que una llamada a c_str() quiere hacer algunas copias aunque no conozco ningún implementaciones donde hace.

+0

Ah, gracias por eso, lo probaré. Se ve mucho más simple de lo que imaginaba que sería :) – kamziro

2

Solo hay una copia porque el parámetro que pasa, un const char*, requiere la conversión al tipo de argumento del istringstream constructor.

Solo pase en el string sin llamar al c_str().

istringstream iss(moo); 

Bien, eso no impide la copia por completo, pero elimina una copia innecesaria. Para eliminar por completo la copia, debe volver a escribir std::stringbuf, lo que evita trabajar directamente en el string que le proporcione.

2

Depende de lo que hace std :: string. De acuerdo con 27.2.1/1 The class basic_istringstream<charT,traits,Allocator> ... uses a basic_stringbuf<charT,traits,Allocator> object to control the associated storage. Como la clase debe usar un objeto, debe copiar la cadena en ese objeto.

Así que la verdadera pregunta no es si un stringstream copia el contenido, pero si la copia de construir una cadena copiará el contenido o implementará algún tipo de esquema de copia sobre escritura.

3

obsoleto istrstream admite esta característica.

#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_ 
} 
+0

Usando 'capacity()' es incorrecto, esto debería ser 'size()'. – sbi

+0

@sbi: mi mal, hice algunas pruebas con strstream primero, fue un remanente de eso, bueno, está arreglado ahora. – smerlin

2

El uso de istringstream no es una solución satisfactoria, ya que esto copia todo el almacenamiento intermedio.

Una respuesta anterior sugiere la istrstream en desuso, pero ya que esto genera avisos y puede ser removido en el futuro, una mejor solución es utilizar boost::iostreams:

boost::iostreams::stream<boost::iostreams::array_source> stream(moo.c_str(), moo.size()); 

Esto evita la copia de la memoria intermedia de la misma manera istrstream hicieron y le ahorra tener que escribir su propia clase de transmisión.

Cuestiones relacionadas