C++ <vector> оператор operator[]
Среди всех способов доступа к элементам vector,operator[]— самый распространённый и прямой вариант, точно так же, как доступ к элементам массива.
operator[]— это оператор индексации классов-контейнеров, используемый длявозврата элемента в указанной позиции, но он не выполняет проверку границ. Его использование точно такое же, как у обычного массива.
operator[]обеспечивает возможность произвольного доступа в стиле массива, позволяя быстро обращаться к элементам в любой позиции.
Определения слов: operator[]— это оператор индексации, а квадратные скобки — символ доступа к массиву.
Базовый синтаксис и параметры
operator[]— это функция-член класса-контейнера. Просто используйте её так же, как массив.
Формат синтаксиса
reference operator[](size_type pos); const_reference operator[](size_type pos) const;
Описание параметра
- Параметр:
pos- Тип:
size_type(беззнаковый целочисленный тип, обычноsize_t) - Описание: позиция (индекс) элемента, к которому нужно получить доступ. Индекс начинается с 0, а максимальный допустимый индекс равен
size() - 1。
- Тип:
Описание функции
- Возвращаемое значение: возвращает ... элемента в указанной позицииСсылка. Если контейнер является константным контейнером, возвращается константная ссылка.
- Эффект: возвращает элемент в указанной позиции. Проверка границ не выполняется; доступ за границы приводит к неопределённому поведению.
- Отличие от at():
operator[]Не выполняет проверку границ, поэтому работает немного быстрее;at()выполняет проверку границ и выбрасывает исключение при выходе за границы.
Пример
Давайте основательно освоим его с помощью серии примеров — от простых к сложным.operator[]Использование.
Пример 1: Базовое использование - доступ к элементам
Пример
#include <vector>
int main() {
// 1. Создайте вектор и добавьте несколько элементов
std::vector<int> numbers = {10, 20, 30, 40, 50};
std::cout << "Размер вектора: " << numbers.size() << std::endl;
// 2. Используйте operator[] для доступа к элементам
std::cout << "Первый элемент [0]: " << numbers[0] << std::endl;
std::cout << "Второй элемент [1]: " << numbers[1] << std::endl;
std::cout << "Третий элемент [2]: " << numbers[2] << std::endl;
std::cout << "Последний элемент [4]: " << numbers[4] << std::endl;
// 3. Использование цикла для доступа ко всем элементам
std::cout << "Все элементы: ";
for(size_t i = 0; i < numbers.size(); ++i) {
std::cout << numbers[i] << " ";
}
std::cout << std::endl;
return 0;
}
Ожидаемый вывод:
vector的大小是: 5 第一个元素 [0]: 10 第二个元素 [1]: 20 第三个元素 [2]: 30 最后一个元素 [4]: 50 所有元素: 10 20 30 40 50
Анализ кода:
numbers[0]Возвращает первый элемент10(индексы начинаются с 0).numbers[4]возвращает последний элемент50(потому чтоsize()равно 5, а допустимые индексы — 0-4).- используя циклы и
operator[]может обходить все элементы, и его использование точно такое же, как у массива.
Пример 2: Изменение значений элементов
operator[]возвращает ссылку, поэтому его можно использовать для изменения значения элемента.
Пример
#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[i] << " ";
}
std::cout << std::endl;
// Используйте operator[] для получения ссылки и изменения элементов
numbers[0] = 100;
numbers[1] = 200;
numbers[2] = 300;
std::cout << "After modification: ";
for(size_t i = 0; i < numbers.size(); ++i) {
std::cout << numbers[i] << " ";
}
std::cout << std::endl;
return 0;
}
Ожидаемый вывод:
修改前: 10 20 30 修改后: 100 200 300
Анализ кода:
numbers[0] = 100;Значение первого элемента было изменено через ссылку.- Это демонстрирует
operator[]возвращает изменяемую lvalue-ссылку.
Пример 3: Использование auto для автоматического вывода типа
Комбинацияautoключевое слово, для более удобного использованияoperator[]。
Пример
#include <vector>
#include <string>
int main() {
std::vector<std::string> names = {"Alice", "Bob", "Charlie"};
// Используйте auto для автоматического вывода типа
for(size_t i = 0; i < names.size(); ++i) {
auto& name = names[i]; // Выводится как std::string&
std::cout << "Раунд " << (i + 1) << " человек: " << name << std::endl;
}
return 0;
}
Ожидаемый вывод:
第 1 个人: Alice 第 2 个人: Bob 第 3 个人: Charlie
Анализ кода:
auto& name = names[i];Автоматически выводится какstd::string&, что позволяет напрямую изменять элемент.Пример 4: Разница между operator[] и at()
Сравнениеoperator[]иat()Различия в поведении.
Пример
#include <vector>
#include <stdexcept>
int main() {
std::vector<int> numbers = {10, 20, 30};
// operator[] не выполняет проверку границ; доступ за границы — на ваш риск
// Здесь происходит доступ к numbers[5], но size() возвращает 3, это неопределённое поведение
// Для демонстрации мы обращаемся только к допустимому диапазону
std::cout << "доступ через operator[]:" << std::endl;
for(size_t i = 0; i < 3; ++i) {
std::cout << "numbers[" << i << "] = " << numbers[i] << std::endl;
}
std::cout << "\nдоступ через at() (с проверкой границ):" << std::endl;
for(size_t i = 0; i < 3; ++i) {
std::cout << "numbers.at(" << i << ") = " << numbers.at(i) << std::endl;
}
std::cout << "\nСовет: используйте operator[], когда уверены, что индекс не выйдет за границы, << std::endl;
std::cout << " Используйте at(), когда не уверены, чтобы получить защиту через исключения." << std::endl;
return 0;
}
Анализ кода:
operator[]Доступ быстрее, потому что проверка границ не выполняется.at()Безопаснее, но с накладными расходами на обработку исключений.- Совет по выбору: если индекс гарантированно безопасен (например, переменная цикла от 0 до size()-1), используйте
operator[]; если индекс поступает из внешнего ввода или может быть неопределённым, используйтеat()。
Пример 5: Вычисление скалярного произведения векторов
Использованиеoperator[]Реализуйте операции с векторами.
Пример
#include <vector>
// Вычислить скалярное произведение двух векторов
int dotProduct(const std::vector<int>& v1, const std::vector<int>& v2) {
int result = 0;
for(size_t i = 0; i < v1.size(); ++i) {
result += v1[i] * v2[i];
}
return result;
}
int main() {
std::vector<int> v1 = {1, 2, 3};
std::vector<int> v2 = {4, 5, 6};
int result = dotProduct(v1, v2);
std::cout << "Вектор v1: ";
for(size_t i = 0; i < v1.size(); ++i) {
std::cout << v1[i] << " ";
}
std::cout << std::endl;
std::cout << "Вектор v2: ";
for(size_t i = 0; i < v2.size(); ++i) {
std::cout << v2[i] << " ";
}
std::cout << std::endl;
std::cout << "Скалярное произведение: " << result << std::endl;
// 1*4 + 2*5 + 3*6 = 4 + 10 + 18 = 32
return 0;
}
Ожидаемый вывод:
向量 v1: 1 2 3 向量 v2: 4 5 6 点积: 32
Анализ кода:
- Использование
operator[]позволяет быстро обращаться к элементам вектора в алгоритмах. - Скалярное произведение вычисляется путём умножения элементов, стоящих на соответствующих позициях, и последующего их суммирования.
Другие расширения