stl — C ++ Странное поведение с ostringstream

Есть ли какое-либо объяснение в стандарте для приведенного ниже поведения?

Следующий код:

#include <sstream>
#include <iostream>

using namespace std;

int main()
{
ostringstream os1;
ostringstream os2;

os1 << 1 << " " << 2;
os2 << 1 << " " << 2 << " " << 3;

const char *p = os1.str().c_str();

cout << os2.str() << endl;
cout << p << endl;

return 0;
}

отображает вывод:

1 2 3
1 2 3

Тем не менее, я ожидаю, что это покажет:

1 2 3
1 2

Похоже, что объект os1 каким-то образом находится под влиянием os2, если я уберу вызов os2.str (), пример будет работать правильно.

Я попробовал пример, если Solaris Studio 12.2 и G ++ 4.8.1 и оба ведут себя одинаково.

Спасибо за вашу помощь!

2

Решение

const char *p = os1.str().c_str();

Вот проблема, в вышеприведенной строке.

os1.str() возвращает временный строковый объект путем копирования внутреннего строкового буфера. И вы принимаете .c_str() временного объекта, который уничтожается в конце полного выражения. В результате p указывает на разрушенный объект, когда вы берете его на печать с помощью std::cout,

То есть ваша программа вызывает неопределенное поведение (UB).

Попробуй это:

auto s = os1.str();
const char *p = s.c_str(); //s is not a temporary object anymore!

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

3

Другие решения

Я думаю, что проблема связана с сохранением указателя, возвращенного c_str(),

ostringstream::str() возвращает временный строковый объект, и вы сохраняете указатель на его внутренний char массив. Но после выполнения этой строки возвращенный строковый объект будет удален. Таким образом, ваш указатель будет недействительным.

Если по какой-то причине вы хотите сохранить указатель c_str, вам также необходимо сохранить копию строки:

string s = os1.str();
const char *p = s.c_str();

cout << os2.str() << endl;
cout << p << endl;
2

Ответ на этот вопрос здесь:
путаница преобразования строк, строк и символов *

stringstream.str () возвращает временный строковый объект, который уничтожается в конце полного выражения. Если вы получите указатель на строку C из этого (stringstream.str (). C_str ()), он будет указывать на строку, которая удаляется в том месте, где заканчивается оператор.

0
По вопросам рекламы [email protected]