На этом шаге мы рассмотрим способы и особенности обращения к отдельным символам строки.
Строки предоставляют возможность чтения и записи хранящихся в них символов. Обращение к отдельному символу производится одним из двух способов: оператором индексирования [] или функцией at(). Обе операции возвращают символ в позиции с заданным индексом. Как обычно, первому символу соответствует индекс 0, а последнему - индекс length()-l. Тем не менее существуют и различия.
Во всех остальных случаях (для неконстантной версии оператора [] и функции at()) индекс, равный текущему количеству символов, считается недействительным. Его использование приводит к исключениям или непредсказуемым последствиям. Пример:
const std::string cs('nico"); // cs содержит символы n, i, c, o std.rstring s("abcde"); // s содержит символы a, b, c, d, e s[2] // Символ с s.at(2) // Символ с s[100] // ОШИБКА: непредсказуемые последствия s.at(100) // Исключение out_of_range s[s.length()] // ОШИБКА: непредсказуемые последствия cs[cs.length()] // Символ \0 s.at(s.length()) // Исключение out_of_range cs.at(s.length()) // Исключение out_of_range
Чтобы программа могла изменять отдельные символы строки, неконстантные версии [] и at() возвращают ссылки на символы. Помните, что при перераспределении памяти ссылки становятся недействительными:
std::string s("abcde"); // s содержит символы a, b, c, d, e char& r = s[2]; // Ссылка на третий символ char* p = &s[3]; // Указатель на четвертый символ r = 'X'; // ОК. s содержит символы a, b, X, d, e *р = 'Y'; // ОК. s содержит символы a, b, X, Y, e s = "new long value"; // При перераспределении памяти r и р // становятся недействительными r = 'X'; // ОШИБКА: непредсказуемые последствия *р = 'Y'; // ОШИБКА: непредсказуемые последствия
Для предотвращения ошибок времени выполнения необходимо зарезервировать достаточную емкость функцией reserve() перед инициализацией r и р.
Ссылки и указатели, ссылающиеся на символы строки, становятся недействительными при выполнении следующих операций:
Данные условия также относятся к итераторам.
На следующем шаге мы рассмотрим операции стравнения.