Ответ 1
std::string потребуется иметь непрерывное хранилище с новым стандартом С++ 0x. В настоящее время это поведение undefined.
В std::string есть только константные элементы для извлечения данных типа c_str(). Однако я могу получить ссылку на первый элемент строки через operator[]
, и я могу написать ей.
Например, если у меня есть функция:
void toupper(char *first,char *last_plus_one);
Я могу написать прямо в вектор, получая указатель на первый элемент:
vector<char> message // has "Some Message";
toupper(&message[0],&message[0]+message.size());
Могу ли я сделать то же самое с std::string?
string message="Some Message";
toupper(&message[0],&message[0]+message.size());
Является ли стандарт гарантией того, что местоположение памяти фактически линейно? то есть:
&(*(message.begin()+n)) == &message[n]
Спасибо.
std::string потребуется иметь непрерывное хранилище с новым стандартом С++ 0x. В настоящее время это поведение undefined.
Herb Sutter имеет это сказать (http://herbsutter.wordpress.com/2008/04/07/cringe-not-vectors-are-guaranteed-to-be-contiguous/#comment-483):
текущий ISO С++ требует & str [0], чтобы кашлять указатель на непрерывные строковые данные (но не обязательно завершающий нуль!), поэтому в любом случае для исполнителей не было много возможностей для несвязанных строк. Для С++ 0x мы уже приняли гарантию того, что содержимое std::string должно храниться смежно. Подробнее см. http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#530
И Мэтт Аустерн говорит аналогично в ссылочном документе (http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#530).
Итак, кажется, что вы можете предположить, что, как только вы вызываете str [0], вы получаете модифицируемый массив символов (но обратите внимание, что для него не требуется завершение нулями).
Да, вы можете изменить строку.
Вы также можете использовать его в алгоритмах, которые используют итераторы.
Вы не можете использовать его так же, как вектор < > , потому что нет гарантии, что элементы находятся в смежных ячейках памяти (пока: скоро приблизитесь к стандарту).
Итак, если вы измените свой подход, чтобы использовать итераторы, а не указатели, он должен работать. И поскольку итераторы ведут себя очень сильно, как указатели, изменения кода должны быть незначительными.
template<typename I>
void toupper(I first,I last_plus_one)
{
// Probably the same code as you had before.
}
{
std::string s("A long string With Camel Case");
toupper(s.begin(),s.end());
}
Как было указано, можно использовать строки в алгоритмах, которые используют итераторы; тот же случай может быть реализован с помощью std::transform
Ex: - рассмотреть строку 's', которая будет преобразована в нижний регистр:
int (*pf)(int)=tolower; //lowercase
std::transform(s.begin(), s.end(), s.begin(), pf);
Привет,
Я думаю, что он дает вам поведение undefined. Используйте stringstream для записи, а затем используйте элемент str(), чтобы получить строку потока.