Почему "vector.at(x)" лучше, чем "вектор [x]" в С++?
Если я хочу получить значение в векторе, я могу использовать два параметра: используйте оператор []. Или я могу использовать пример функции .at для использования:
vector<int> ivec;
ivec.push_back(1);
Теперь я могу сделать обе вещи
int x1 = ivec[0];
int x2 = ivec.at(0); // or
Я слышал, что использование at - лучший вариант, потому что, когда я использую эту опцию, я могу выбросить это в исключение.
Может кто-нибудь объяснить это?
Ответы
Ответ 1
Разница между c[i]
и c.at(i)
заключается в том, что at()
выдает исключение std::out_of_range
, если i
выходит за пределы диапазона вектора, тогда как operator[]
просто вызывает поведение undefined, что означает, что все может случиться.
Никто не говорит, что at()
лучше, чем operator[]
. Это зависит только от обстоятельств. Поскольку at()
выполняет проверку диапазона, это может быть нежелательно всегда, особенно когда ваш код сам гарантирует, что индекс никогда не может выйти за пределы диапазона. В таких случаях лучше operator[]
.
Рассмотрим следующий цикл:
for(size_t i = 0 ; i < v.size(); ++i)
{
//Should I use v[i] or v.at(i)?
}
В таком цикле operator[]
всегда лучший выбор по сравнению с функцией at()
member.
Я бы предпочел at()
, когда я хочу, чтобы он генерировал исключение в случае недопустимого индекса, так что я мог бы сделать альтернативную работу в блоке catch{ ...}
. Исключения помогают отделить обычный код от исключительного/альтернативного кода следующим образом:
try
{
size_t i = get_index(); //I'm not sure if it returns a valid index!
T item = v.at(i); //let it throw exception if i falls outside range
//normal flow of code
//...
}
catch(std::out_of_range const & e)
{
//alternative code
}
Здесь вы можете проверить i
самостоятельно, чтобы убедиться, что он является допустимым индексом, а затем вызовите operator[]
вместо at()
, но он будет смешивать обычный код с альтернативным кодом с помощью блока if-else
что затрудняет чтение нормального потока кода. Если вы видите выше, try-catch
улучшает читаемость кода, так как он действительно отделяет нормальный код от альтернативного кода, что приводит к аккуратным и чистым кодам.
Ответ 2
Единственное различие между at
и []
заключается в том, что at
выполняет проверку диапазона, а []
- нет. Если вы уже проверили диапазон или создали свой индекс таким образом, чтобы он не мог выйти из диапазона, и вам нужно получить доступ к элементу повторно, вы можете сэкономить несколько циклов процессора, выбрав []
вместо at
.
Пример одной проверки и множественного доступа:
size_t index = get_index(vect);
if (index < 0 || index >= vect.size()) return;
if (vect[index] > 0) {
// ....
} else if (vect[index] > 5) {
// ....
} else ....
Пример случая, когда индекс построен внутри пределов:
for (size_t i = 0 ; i != vect.size() ; i++) {
if (vect[i] > 42) {
// ....
}
}
Ответ 3
Другие ответы являются полностью правильными, но могут создать впечатление, что рекомендуется использовать at()
при написании кода, который вы все еще будете отлаживать, поскольку это вызовет сообщение об ошибке. Это в общем случае, но не применимо к большинству распространенных компиляторов - gcc может быть настроен на выполнение (фатальный) проверки диапазона с помощью поместить его в режим отладки и что-то подобное возможно, возможно, будет сделано в Visual Studio.
Ответ 4
Векторный метод С++ .at
проверяет границы, поэтому, когда элемент не существует в векторе и исключение out_of_range
.
При использовании []
для вектора не выполняется проверка привязки, поэтому, если элемент не существует, исключение не генерируется, и результат представляет собой поведение undefined, такое как случайные значения, не содержащие exeisting elemnts в векторе.
Использование []
лучше, чем at
с точки зрения безопасности, однако это потребует больше времени и оказывает влияние на перферманс программы.