сброс строкового потока


86

Как мне «сбросить» состояние строкового потока до того, каким оно было при его создании?

int firstValue = 1;
int secondValue = 2;

std::wstringstream ss;

ss << "Hello: " << firstValue;

std::wstring firstText(ss.str());

//print the value of firstText here


//How do I "reset" the stringstream here?
//I would like it behave as if I had created
// stringstream ss2 and used it below.


ss << "Bye: " << secondValue;

std::wstring secondText(ss.str());

//print the value of secondText here

Ответы:


134

Я обычно так делаю:

ss.str("");
ss.clear(); // Clear state flags.

Благодарность; отлаживать чужой C ++ и это необходимо для устранения ошибки нарушения прав доступа, которую они получали из-за невыполнения метода .clear (). Работал нормально на приставке Intel, но каждый раз рвал на машине AMD.
— Крис Таунсенд

3
К сожалению clear, не сбрасывает манипуляторы io. Пример неудачного теста: std :: stringstream ss; ss << "Привет" << std :: setw (15) << "Мир" << std :: setw (15); сбросить (сс); ss << "Hello World"; assert ("Привет, мир" == buf.str ()); // терпит неудачу, берет последний std ::
— setw

9

я бы сделал

std::wstringstream temp;
ss.swap(temp);

Изменить: исправлена ​​ошибка, о которой сообщили christianparpart и Nemo. Спасибо.

PS: Приведенный выше код создает новый объект строкового потока в стеке и меняет местами все, что ssесть в новом объекте.

Преимущества:

  1. Он гарантирует, ssчто теперь будет в свежем-новом состоянии.
  2. Новый объект создается встроенным и в стеке, так что компилятор может легко оптимизировать код. В конечном итоге это будет похоже на сброс всех ssвнутренних данных в исходное состояние.

Больше:

  1. По сравнению с оператором присваивания: методы подкачки STL могут быть быстрее, чем оператор присваивания, в тех случаях, когда новый объект имеет выделенный буфер в куче. В таком случае оператор присваивания должен выделить буфер для нового объекта, затем МОЖЕТ потребоваться выделить другой буфер для старого объекта, а затем скопировать данные из буфера нового объекта в новый буфер старого объекта. Очень легко реализовать быструю подкачку, например, просто поменять местами указатели буферов.

  2. С ++ 11. Я видел некоторую реализацию оператора присваивания перемещения, которая работает медленнее, чем своп, хотя это можно исправить, но, вероятно, разработчик STL не захочет оставлять перемещенный объект с большим количеством данных

  3. std::move()не гарантирует, что перемещенный объект опустеет. return std::move(m_container);не очищает m_container. Так что тебе придется сделать

    авто to_return (std :: move (m_container)); m_container.clear (); return to_return;

Что не может быть лучше, чем

auto to_return;
m_container.swap(to_return);
return to_return;

потому что последний гарантирует, что не будет копировать буферы.

Так что я всегда предпочитаю swap()столько, сколько подходит.


2
Вы должны объяснить, почему вы это сделали. Сам по себе этот код не очень полезен.
— Machavity

1
Хотя этот ответ может быть правильным, пожалуйста, добавьте пояснения. Передача базовой логики важнее, чем просто предоставление кода, потому что это помогает OP и другим читателям исправить эту и подобные проблемы самостоятельно.
— CodeMouse92 05

Мне нравится решение. Он очень короткий, и один и тот же шаблон работает практически для всех стандартных типов данных.
— Мартинус

1
Этот ответ не совсем правильный, так как вы не можете выполнить привязку к временной, то есть вы создаете временную переменную для замены вновь (временно) созданного потока пустой строки на существующий поток «ss». Не допускается.
— christianparpart

Разве это не влечет за собой все накладные расходы на создание локали, которых предполагается избежать при сбросе строкового потока?
— матчи за сборную

2

Основываясь на ответе выше, нам также необходимо сбросить любое форматирование. В общем, мы сбрасываем содержимое буфера, флаги состояния потока и любое форматирование до значений по умолчанию, когда создается новый экземпляр std :: stringstream.

void reset(std::strinstream& stream)
{
    const static std::stringstream initial;

    stream.str(std::string());
    stream.clear();
    stream.copyfmt(initial);
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.