Законно ли писать в std::string?
В std:: string есть только члены const для извлечения данных, например 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]
Благодарю.
5 ответов
std::string будет иметь непрерывное хранилище с новым стандартом C++0x. В настоящее время это неопределенное поведение.
Херб Саттер говорит следующее ( http://herbsutter.wordpress.com/2008/04/07/cringe-not-vectors-are-guaranteed-to-be-contiguous/):
текущий ISO C++ действительно требует, чтобы &str[0] выкашлял указатель на непрерывные строковые данные (но не обязательно заканчивающиеся нулем!), так что у разработчиков не было особой возможности иметь несмежные строки в любом случае. Для C++0x мы уже приняли гарантию того, что содержимое std::string действительно должно храниться непрерывно. Для получения дополнительной информации см. http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html
И Мэтт Остерн говорит, что подобное в указанном документе ( http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html).
Таким образом, кажется, что вы можете предположить, что после вызова 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
Пример:- считать строку 's' преобразованной в нижний регистр:
int (*pf)(int)=tolower; //lowercase
std::transform(s.begin(), s.end(), s.begin(), pf);
С Уважением,
Я думаю, что это дает вам неопределенное поведение. Используйте строковый поток для записи, а затем используйте член str() для получения строки потока.