скидання потокового рядка


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); ss << "Привіт Світ"; assert ("Hello World" == buf.str ()); // не вдається, піднімає останній std :: setw
GameSalutes

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 (); повернутися до_повернення;

Що не може бути кращим за

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

оскільки остання гарантує, що не буде копіювати буфери.

Тому я завжди віддаю перевагу swap(), поки це підходить.


2
Вам слід пояснити, чому ви це робите. Цей код не дуже корисний сам по собі.
Machavity

1
Хоча ця відповідь може бути правильною, будь ласка, додайте пояснення. Додавання базової логіки важливіше, ніж просто надання коду, оскільки це допомагає ОП та іншим читачам самостійно виправити цю та подібні проблеми.
CodeMouse92

Мені подобається рішення. Він дуже короткий, і один і той же шаблон працює практично для всіх типів даних std.
martinus

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.