Должен ли я повторять вектор с помощью итератора или оператора доступа?

У меня вектор объявлен как

std::vector<int> MyVector;
MyVector.push_back(5);
MyVector.push_back(6);
MyVector.push_back(7);

Как я должен использовать его в цикле?

Итерируя это с помощью итератора?

for (std::vector<int>::iterator it=MyVector.begin(); it!=MyVector.end(); ++it)
{
std::cout << "Vector element (*it): " << *it << std::endl;
}

Или его итератором доступа?

for (std::vector<int>::size_type i=0; i<MyVector.size(); i++)
{
std::cout << "Vector element  (i) : " << MyVector.at(i) << std::endl;
}

В примерах, которые я нашел в интернете, они оба используются. Один из них превосходит другой в любых условиях? Если нет, то когда я должен предпочесть один из них другому?

5

Решение

Первый формат более общий формат для перебора стандартных контейнеров библиотеки, чтобы он был более распространенным и интуитивно понятным. Если вам нужно изменить ваш контейнер, тогда этот итерационный код останется неизменным. Он будет работать для каждого стандартного типа контейнера библиотеки, таким образом, он даст вам более общий код.

Во втором формате std::vector::at() проверяет границы каждый раз, когда он вызывается на каждой итерации, так что это может быть немного вредно для производительности. Эти издержки не присутствуют в первом формате, так как здесь не выполняется проверка границ. Обратите внимание, что то же самое относится и к использованию operator[],
Обратите внимание, что отставание в производительности не так сильно, как вы заметите, если только вы не оперируете большими данными.

5

Другие решения

С помощью std::vector's [] operator вероятно, быстрее, потому что с помощью std::vector::at() внутри цикла for дважды проверяет размер вектора (в цикле for и в проверке границ std :: vector :: at ()).

Первый метод может использоваться в других контейнерах и, таким образом, может сильно помочь вам при изменении типа контейнера.

Если вы используете C ++ 11, используйте циклы на основе диапазона.

3

Во-первых, если у вас есть C ++ 11, используйте диапазон для:

for (auto i : MyVector)
{
std::cout << i;
}

Или же BOOST_FOREACH в C ++ 03:

BOOST_FOREACH(int& i, MyVector)
{
std::cout << i;
}

Или же std::copy:

std::copy(MyVector.begin(),
MyVector.end(),
std::ostream_iterator<int>(std::cout, "\n"));

Что касается вопроса под рукой, at() проверяет, что индекс находится в пределах границ, и выдает исключение, если это не так. Так что не используйте его, если вам не нужна дополнительная проверка. Первый способ, которым вы пользуетесь, является стандартным и работает хорошо. Некоторые люди педантичны и даже пишут так:

for (std::vector<int>::iterator it=MyVector.begin(), end = MyVector.end(); it!= end; ++it)
{
std::cout << "Vector element (*it): " << *it << std::endl;
}

В приведенном выше я кэшировал end итератор вместо вызова end() каждая петля. Независимо от того, влияет ли это на производительность или нет, я не знаю.

2

Там нет «один превосходит другого» (за исключением того, что вы почти никогда
хочу использовать at()at() уместно только если есть
что-то, что вы действительно можете сделать, чтобы оправиться от ошибки). Использование
Итератор против индекса во многом зависит от стиля, и сообщение, которое вы
прохождение. Более идиоматическим способом выполнения C ++ будет
итератор, но люди приходят из других слоев населения (например,
математики) найдут индексирование более идиоматическим.

Вот где есть настоящее различие:

  • Идиома итератора будет работать с другими типами контейнеров. это
    может иметь значение, если есть реальная возможность того, что вы используете другие
    контейнеры.

  • Идиома индексации может использовать один индекс для нескольких разных
    контейнеры. Если вы перебираете несколько vector с тем же
    размер, используя идиому индексации, делает более понятным, что вы обращаетесь
    один и тот же элемент в каждом из vector, (Опять же, это, кажется, происходит
    чаще всего в математических приложениях.)

  • Наконец, каждый раз, когда вы действительно делаете произвольный доступ или вычисляете
    элемент в любом случае, используя индексы, вероятно, более интуитивно понятен. (В
    В таких случаях вы, вероятно, хотите сделать расчеты в int, только
    преобразование в size_t в последний момент.)

1
По вопросам рекламы [email protected]