30 мая 2012 г., 21:51 отWilliamKF

Есть ли более эффективный способ установить std :: vector из потока?

В настоящее время я устанавливаю значениеstd::vector<char> изstd::ostringstream следующее:

void
foo(std::vector<char> &data, std::stringstream &stream) {
  data = std::vector<char>(stream.str().begin(), stream.str().end());
}

Мне интересно, есть ли более эффективный способ сделать это с помощью STL в C ++ или метод, который я здесь привожу, считается подходящим? Буду ли я лучше использоватьstd::stringstream вместо?

Ответы на вопрос(0)

31 мая 2012 г., 01:55 отdirkgently

Ты можешь позвонитьreserve на вашейdata и используйте диапазонinsert участник прямо наdata вместо использования копирования-назначения. Вещь оvectorледует помнить, что каждый узел может увеличить размер (и переместить все элементы). Таким образом, вам лучше выделить память за один раз (если вы знаете, сколько объектов вы будете хранить - что вы знаете здесь) и использовать этот факт.

31 мая 2012 г., 01:58 отXeo

неопределенное поведение. stream.str() возвращает строку От стоимости, иначе временная строка. Вы беретеbegin итератор одного временного иend итератор другого, создающий недопустимый диапазон.

Один из способов преобразования потока в контейнер - использовать общий интерфейс итератора:

#include <iostream>
#include <sstream>
#include <vector>
#include <algorithm>
#include <iterator>

int main(){
  std::stringstream src("....");
  std::vector<char> dest;
  // for a bit of efficiency
  std::streampos beg = src.tellg();
  src.seekg(0, std::ios_base::end);
  std::streampos end = src.tellg();
  src.seekg(0, std::ios_base::beg);
  dest.reserve(end - beg);

  dest.assign(std::istreambuf_iterator<char>(src), std::istreambuf_iterator<char>());

  std::copy(dest.begin(), dest.end(), std::ostream_iterator<char>(std::cout));
}

Живой пример на Ideone.

Другой метод - кешировать возвращенныйstd::string объект:

std::string const& s = stream.str();
data.reserve(s.size());
data.assign(s.begin(), s.end());
31 мая 2012 г., 01:55 отK-ballo

ваш код неверен из-за двух вызововstr(). В целях повышения эффективности вы можете избежать создания временногоvector, так

void foo(std::vector<char> &data, std::stringstream &stream) {
    const std::string& str = stream.str();
    data.assign( str.begin(), str.end() );
}

Вы также можете избежатьstd::string используяstd::istreambuf_iterators:

void foo(std::vector<char> &data, std::stringstream &stream) {
    data.assign(
        std::istreambuf_iterator<char>( stream ), std::istreambuf_iterator<char>()
    );
}

но учитывая, что этоinput итераторы,vector не имеет возможности узнать, сколько данных будет назначено и может работать немного хуже, поскольку не можетreserve достаточно места, чтобы избежать перераспределения.

31 мая 2012 г., 02:47 отbrewbuck

std::istream src;
std::vector<char> dst;

std::copy(std::istream_iterator<char>(src), std::istream_iterator<char>(), std::back_inserter(dst));

Istream_iterator использует форматированное преобразование (то есть пропускает пробелы), поэтому это может быть не то, что вам нужно. Я не уверен, какова ваша цель.

ВАШ ОТВЕТ НА ВОПРОС