ostringstream, .str () и сброс / очистка потока

Я зализываю свои раны из Ошибка памяти с std: ostringstream и -std = c ++ 11?, и у меня есть связанный с этим вопрос.

Если следующее возвращает временное значение, так что reserve не действует, а char* недействителен:

ostringstream oss;
oss.str().reserve(96);

// populate oss

const char* ptr = oss.str().c_str();
// do something with ptr

Тогда как следующее очищает ostringstream (из Как повторно использовать ostringstream?):

oss.clear(); oss.str("");

Я понимаю, что clear() сбросит флаги потока; но как я теперь понимаю, str("") будет работать с временной, а не с базовой строкой.

Так как же str("") сбросить поток?


person jww    schedule 22.01.2014    source источник


Ответы (3)


Это разные функции.

oss.str() (без параметров) возвращает копию базовой строки потока, но oss.str("") устанавливает ее базовую строку в значение, которое вы передали (здесь пустая строка: "").

Таким образом, вызов как clear(), так и str("") на std::stringstream фактически "сбрасывает" его.

Обратите внимание на две подписи на cppreference

person JBL    schedule 22.01.2014
comment
clear() сбрасывает флаги ошибок. str("") заменяет входные данные заданной строкой. Эти двое совершенно не связаны. - person James Kanze; 22.01.2014
comment
А если быть точным: oss.str() возвращает копию базовой строки потока. В этом случае важно то, что это копия. - person James Kanze; 22.01.2014
comment
Спасибо, JBL. Я не могу сказать вам, сколько раз я заходил на другую справочную страницу CCP. Я считаю, что комитет по C ++ перегружал поведение и семантику .str() (в одном случае - временная, в другом - псевдоссылка) - это своего рода мерзость. Именно поэтому я подумал, что .str() вернул ссылку на нижележащую строку. - person jww; 22.01.2014
comment
@JamesKanze Ага, это копия. Я написал возврат ... временно, но это было неудобно, поэтому я удалил его, но забыл упомянуть, что это копия. Я поддержу ваш комментарий, чтобы подчеркнуть это. - person JBL; 22.01.2014
comment
@noloader Я думаю, вы неправильно понимаете поведение функции. Здесь нет псевдоссылки, как вы это называете. Вы просто передаете строку в str, который затем выполняет присвоение внутреннему объекту. Ни в коем случае функция не предоставляет вам внутренний объект. - person Joseph Mansfield; 22.01.2014
comment
@JamesKanze и да, эти две функции не связаны, но обе используются для создания впечатления какой-то reset() функции, которая оставляет поток в пустом и чистом (из-за отсутствия лучшего слова) состоянии. - person JBL; 22.01.2014
comment
@noloader В одном случае он ничего не возвращает (когда вы устанавливаете базовое содержимое строки), а в другом случае он возвращается по значению, что означает, что у вас есть копия, не более того. - person JBL; 22.01.2014
comment
Что, я полагаю, вы имели в виду под своего рода. Конечно, ни один из них не сбрасывает поток; они сбрасывают только (относительно небольшую) его часть. Единственный практический способ получить поток в подобном новом состоянии - это создать новый экземпляр. - person James Kanze; 22.01.2014
comment
В одном случае он ничего не возвращает ... а в другом случае он возвращается по значению ... - именно это я и пытаюсь донести. str имеет разное поведение и значение в зависимости от того, как его использовать. Выберите значение и используйте его последовательно. Если вам нужно два поведения, используйте два разных имени функций, чтобы избежать путаницы. - person jww; 22.01.2014
comment
@JamesKanze Да. Но это самое близкое (думаю, поправьте меня, если я ошибаюсь) мы подходим к какой-то перезагрузке. - person JBL; 22.01.2014
comment
@JosephMansfield - я думаю, вы неправильно понимаете поведение функции ... - да, ясно;) И это происходило давно .... - person jww; 22.01.2014
comment
@noloader Ах, сбивает это с толку или нет - это совсем другой спор! : P Затем, когда вы говорите, что str имеет разное поведение и значение в зависимости от того, как он используется, я бы сказал, что есть две str функции, какая из них ?. Я привык к этому, поэтому я не вижу здесь проблемы, но я могу понять путаницу, которую это могло создать. - person JBL; 22.01.2014
comment
@noloader В этом случае комитет просто принял вездесущую идиому C ++: функции перегрузки с именем атрибута, с константной версией без параметров в качестве получателя и неконстантной версией с новым значением в качестве установщика. - person James Kanze; 22.01.2014

Вызов str без аргументов возвращает копию внутреннего строкового объекта. Вот почему это временный объект. Вызов str со строковым аргументом устанавливает значение внутреннего строкового объекта. Он не работает с временным объектом.

Похоже, вы думаете об этом так:

oss.str() = "";

Но это не то. Вы передаете "" функции str, чтобы она могла назначить его внутренней строке.

Он ничем не отличается от любой другой комбинации получателя / сеттера. Если у вас есть getX(), он обычно дает вам копию какого-либо члена класса, для которого вы его вызываете. Если у вас setX(x), он обычно устанавливает значение этого члена. В данном случае они оба называются str, но один принимает аргумент, а другой - нет.

person Joseph Mansfield    schedule 22.01.2014
comment
... он обычно дает вам копию какого-то члена класса, к которому вы его вызываете - на самом деле я выучил это по-другому в колледже (20 лет назад или около того). Если копия была дорогой, вы возвращаете ссылку, а не копию. Строка - дорогостоящий объект, потому что требует вызова new и вызова memcpy. Таким образом, вы должны предоставить версии const и non-const для str() (в моем гипотетическом и неверно информированном случае). - person jww; 22.01.2014

Из этого std::ostringstream::str справочника:

Параметры

new_str - новое содержимое базовой строки

Его можно использовать для получения строки или для установки строки в строку, предоставленную аргументом функции.

person Some programmer dude    schedule 22.01.2014