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

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
user974967
источник

Ответы:

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);
}
GameSalutes
источник