Доступ к элементам вектора
Одним из важных аспектов vector является легкий доступ к его отдельным элементам в произвольном порядке, т.е. по номеру:
template <class T, class A=allocator<T>> class vector {
public:
//…..
// доступ к элементам:
// доступ без проверки диапазона индекса
//(выхода индекса за границы массива)
reference operator[] (size_type n);
const_reference operator[] (size_type n) const;
//доступ с проверкой диапазона индекса
reference at (size_type n);
const_reference at (size_type n) const;
// Ссылка на первый элемент
reference front();
const_reference front() const;
// Ссылка на последний элемент
reference back();
const_reference back() const;
//…..
};
Тип reference (ссылка) илиconst_reference(константная ссылка) (в зависимости от того, применяются ли они к объекту типаconstили нет) удобен для доступа к элементам.
Например, можно написать v[1]=5;x=v[3]; - обычные ссылки могут стоять как в левой, так и в правой части оператора присваивания. Если жеx– константный вектор (например, параметр, переданный функции как константная ссылка на вектор, или член константной функции класса), тоoperator[] и функцияatвозвратят константную ссылку, которая может стоять только в правой части оператора присваивания.
При первом рассмотрении можно рассматривать vector<X>::reference какX&, а vector<X>::const_reference – какconst X&.
Индексация осуществляется operator[] () и функциейat(); operator[] () обеспечивает доступ к элементам, не проверяя, не выходит ли индекс за границы вектора, а функцияat() осуществляет проверку диапазона и возбуждает исключениеout_of_range, если индекс выходит за его пределы. Например:
void f(vector <int>&v, int i1, int i2)
try
{
for (int i=0; i<v.size(); i++) {
// размер уже проверен, используем v[i] без проверки
}
v.at(i1) = v[i2]; // Здесь может произойти исключение out_of_range, если i1 выходит за границы вектора. Если i2 выходит за границы, то произойдет просто крах программы.
//…..
}
catch(out_of_range)
{
//ошибка диапазона
}
Т.е., если есть уверенность в том, что индекс корректный, можно безопасно использовать оператор индексации [] без проверки; в противном случае разумно использовать функцию at(). Преимущество отсутствия проверки в быстродействии. Также можно пользоваться адаптацией классаvector, проверяющей диапазон, по имениVec. (Этот класс разработан в качестве примера и не содержится вSTL). Он во всем похож наvector и будет генерировать исключениеout_of_range, если индекс выходит за его пределы.
template <class T> class Vec : public vector <T> {
public:
Vec() : vector <T> {}
Vec(int s) : vector <T>(s) {}
T& operator[] (int i) {return at(i);}
Const T& operator[] (int i) const {return at(i);}
};
Функции-члены класса vectorfront() иback() возвращают ссылки (referenceилиconst_reference, в зависимости от контекста) на первый и последний элемент соответственно. Функцияfront() возвращает ссылку на элемент, итератор которого возвращает функцияbegin()4. Соотношение междуback() иend() несколько сложнее:back() – возвращает ссылку на последний элемент, аend() указывает на позицию элемента, следующего за последним.