Подтвердить что ты не робот

Почему "vector.at(x)" лучше, чем "вектор [x]" в С++?

Если я хочу получить значение в векторе, я могу использовать два параметра: используйте оператор []. Или я могу использовать пример функции .at для использования:

vector<int> ivec;
ivec.push_back(1);

Теперь я могу сделать обе вещи

int x1 = ivec[0];
int x2 = ivec.at(0); // or

Я слышал, что использование at - лучший вариант, потому что, когда я использую эту опцию, я могу выбросить это в исключение.

Может кто-нибудь объяснить это?

4b9b3361

Ответ 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 с точки зрения безопасности, однако это потребует больше времени и оказывает влияние на перферманс программы.