C++ <vector> функция at
Среди всех способов доступа к элементам vector,atявляется самым безопасным, поскольку обеспечиваетпроверку границ。
atявляется функцией-членом классов-контейнеров, используется длявозврата элемента в указанной позиции, при этом выполняя проверку границ. Если индекс выходит за границы, выбрасывает исключениеstd::out_of_rangeисключение.
atреализует безопасный доступ к элементам, позволяя перехватывать и обрабатывать ошибки выхода за границы во время выполнения.
Определения слов: atозначает «at», т.е. получает элемент в указанной позиции.
Базовый синтаксис и параметры
atявляется функцией-членом класса-контейнера, поэтому сначала нужно иметь объект контейнера, а затем использовать оператор точка.чтобы вызвать её.
Формат синтаксиса
reference at(size_type pos); const_reference at(size_type pos) const;
Описание параметра
- Параметр:
pos- Тип:
size_type(беззнаковый целочисленный тип, обычноsize_t) - Описание: Позиция (индекс) элемента, к которому нужно получить доступ. Индекс начинается с 0, а максимальный допустимый индекс —
size() - 1。
- Тип:
Описание функции
- Возвращаемое значение: возвращает ссылку на элемент в указанной позицииСсылка. Если контейнер является const-контейнером, возвращается const-ссылка.
- Действие: Возвращает элемент в указанной позиции. Если индекс находится вне допустимого диапазона (
pos >= size()), он выбросит исключениеstd::out_of_rangeисключение. - отличие от operator[]:
atвыполняет проверку границ,operator[]не выполняет проверку границ (поведение при выходе за границы не определено).
Пример
Давайте тщательно освоим это с помощью серии примеров, от простого к сложномуatИспользование.
Пример 1: Базовое использование - доступ к элементам
Пример
#include <vector>
#include <stdexcept> // Содержит заголовочный файл обработки исключений
int main() {
// 1. Создайте вектор и добавьте несколько элементов
std::vector<int> numbers = {10, 20, 30, 40, 50};
std::cout << "Размер вектора: " << numbers.size() << std::endl;
⟦⟧// 2. Использование для доступа к элементам
std::cout << Первый элемент (at(0)): << numbers.at(0) << std::endl;
std::cout << Второй элемент (at(1)): << numbers.at(1) << std::endl;
std::cout << Третий элемент (at(2)): << numbers.at(2) << std::endl;
std::cout << Последний элемент (at(4)): << numbers.at(4) << std::endl;
// 3. Использование цикла для доступа ко всем элементам
std::cout << "Все элементы: ";
for(size_t i = 0; i < numbers.size(); ++i) {
std::cout << numbers.at(i) << " ";
}
std::cout << std::endl;
return 0;
}
Ожидаемый вывод:
vector的大小是: 5 第一个元素 (at(0)): 10 第二个元素 (at(1)): 20 第三个元素 (at(2)): 30 最后一个元素 (at(4)): 50 所有元素: 10 20 30 40 50
Анализ кода:
numbers.at(0)Возвращает первый элемент10(индексы начинаются с 0).numbers.at(4)возвращает последний элемент50(потому чтоsize()равно 5, допустимые индексы — 0-4).- используя циклы и
atможно безопасно обойти все элементы.
Пример 2: перехват исключения выхода за пределы диапазона
atОсновное преимущество в том, что он может выбрасывать исключения, позволяя нам обрабатывать ошибки выхода за границы.
Пример
#include <vector>
#include <stdexcept>
int main() {
std::vector<int> numbers = {10, 20, 30};
// Попытка доступа к позиции за границами
try {
std::cout << Попытка доступа к at(10)... << std::endl;
int value = numbers.at(10); // Это вызовет исключение
std::cout << Значение: << value << std::endl;
}
catch(const std::out_of_range& e) {
std::cout << Перехвачено исключение: << e.what() << std::endl;
}
// Обычный доступ
try {
std::cout << Доступ к элементу at(2): << numbers.at(2) << std::endl;
}
catch(const std::out_of_range& e) {
std::cout << Перехвачено исключение: << e.what() << std::endl;
}
return 0;
}
Ожидаемый вывод:
尝试访问 at(10)... 捕获到异常: vector::_M_range_check: __pos (which is 10) >= this->size() (which is 3) 访问 at(2): 30
Анализ кода:
- При доступе
at(10)когда индекс выходит за пределы диапазона, выбрасывается исключениеstd::out_of_rangeисключение. catch(const std::out_of_range& e)Перехватить исключение,e.what()возвращает описание исключения.- обычный доступ по индексу не выбрасывает исключений.
Пример 3: Сравнение at и operator[]
Сравнениеatиoperator[]Различия в поведении.
Пример
#include <vector>
#include <stdexcept>
int main() {
std::vector<int> numbers = {10, 20, 30};
std::cout << Используйте at() для доступа к элементам: << std::endl;
// at() выполняет проверку границ
for(size_t i = 0; i <= numbers.size(); ++i) {
try {
std::cout << "at(" << i << ") = " << numbers.at(i) << std::endl;
}
catch(const std::out_of_range& e) {
std::cout << "at(" << i << ) Выход за пределы диапазона! << std::endl;
}
}
std::cout << "\nИспользуйте operator[] для доступа к элементам: << std::endl;
// operator[] не выполняет проверку границ; поведение при выходе за пределы не определено
for(size_t i = 0; i <= numbers.size(); ++i) {
std::cout << "numbers[" << i << "] = " << numbers[i] << std::endl;
}
return 0;
}
Анализ кода:
at()При выходе за пределы выбрасывается исключение, и вы можете перехватить и обработать его.operator[]поведение при выходе за пределы не определено и может вернуть мусорные значения, вызвать сбой или привести к другим непредсказуемым результатам.- в рабочем коде для безопасности рекомендуется использовать
at()вместо этогоoperator[], особенно когда индекс поступает из пользовательского ввода или внешних данных.
Пример 4: изменение значений элементов
atОн возвращает ссылку, поэтому его можно использовать для изменения значения элемента.
Пример
#include <vector>
int main() {
std::vector<int> numbers = {10, 20, 30};
std::cout << "До изменения: ";
for(size_t i = 0; i < numbers.size(); ++i) {
std::cout << numbers.at(i) << " ";
}
std::cout << std::endl;
// Используйте at() для получения ссылки и изменения элемента
numbers.at(0) = 100;
numbers.at(1) = 200;
numbers.at(2) = 300;
std::cout << "After modification: ";
for(size_t i = 0; i < numbers.size(); ++i) {
std::cout << numbers.at(i) << " ";
}
std::cout << std::endl;
return 0;
}
Ожидаемый вывод:
修改前: 10 20 30 修改后: 100 200 300
Анализ кода:
numbers.at(0) = 100;Значение первого элемента было изменено через ссылку.- Это демонстрирует
at()возвращает изменяемую lvalue-ссылку.
Другие расширения