не копирующий istringstream - PullRequest
10 голосов
/ 26 июня 2010

Так istringstream копирует содержимое строки при инициализации, например,

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

Мне было интересно, есть ли способ заставить std::istringstream использовать данное c_str в качестве буфера без копирования. Таким образом, не нужно будет копировать большие биты памяти перед передачей std::istringstream& функциям, которые принимают istream& в качестве аргумента.

То, что я пытался сделать, - это преобразовать некоторые функции, которые принимают std::ifstream& аргументы (в основном это парсеры), в istream&. Должен ли я сделать свой собственный подкласс istream для этого?

Ответы [ 5 ]

5 голосов
/ 09 июня 2016

Использование istringstream не является удовлетворительным решением, поскольку при этом копируется весь буфер.

Предыдущий ответ предполагает устаревший istrstream, но, поскольку он генерирует предупреждения и может быть удален в будущем, лучшим решением будет использование boost :: iostreams :

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

Это позволяет избежать копирования буфера таким же образом, как это было istrstream, и избавляет вас от необходимости писать собственный класс потока.

3 голосов
/ 26 июня 2010

Довольно просто написать базовый класс std::streambuf, который читает из заданной области памяти. Затем вы можете построить istream из этого и прочитать из этого.

инициализация C ++ std :: istringstream из буфера в памяти?

Обратите внимание, что время жизни буфера, указанного как c_str(), очень ограничено, и нет гарантии, что вызов c_str() захочет вызвать некоторое копирование, хотя я не знаю ни одной реализации, где это происходит.

3 голосов
/ 26 июня 2010

устаревший istrstream поддерживает эту функцию.

#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_
}
2 голосов
/ 26 июня 2010

Это зависит от того, что делает std :: string.Согласно 27.2.1 / 1 The class basic_istringstream<charT,traits,Allocator> ... uses a basic_stringbuf<charT,traits,Allocator> object to control the associated storage. Поскольку класс должен использовать объект, он должен скопировать конструкцию строки в этот объект.

Таким образом, реальный вопрос не в том, копирует ли stringstream содержимое, а в том,copy, создающий строку, будет копировать содержимое или реализовывать какую-либо схему копирования при записи.

2 голосов
/ 26 июня 2010

Существует только копия, потому что передаваемый параметр const char* требует преобразования в тип аргумента конструктора istringstream .

Просто передайте string без вызоваc_str().

istringstream iss(moo);

Хорошо, это не мешает копированию полностью, но устраняет ненужную копию.Чтобы полностью удалить копию, вам нужно будет переписать std::stringbuf, что исключает непосредственную работу с указанным вами string.

...