Итерация структуры данных Vector / Map C ++ - PullRequest
2 голосов
/ 15 февраля 2011

В наши дни я широко использую карту / вектор, но сомневаюсь в их повторении

Какой из них лучше?

for(vector<string>::iterator it=myvec.begin(); it!=myvec.end(); ++it){
}

или

for(int i=0; i < myvec.size(); i++){ 
       myvec[i]
}

Прежде всего, они должны делать то же самое?

Ответы [ 5 ]

1 голос
/ 15 февраля 2011

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

Если вы просто пытаетесь что-то сделать для каждого элемента, вы можете использовать BOOST_FOREACH .

std::list<int> list_int( /*...*/ );
BOOST_FOREACH( int i, list_int )
{
    // do something with i
}
1 голос
/ 15 февраля 2011

Когда вы используете ручной цикл, это не имеет большого значения.Но когда вы работаете с функциями STL (скажем, с <algorithm>), у вас нет выбора.Вы должны использовать итератор, так как функции STL работают с итератором, а не с индексом.

Например, если вы хотите вычислить сумму всех целых чисел в vector<int>, используя std::accumulate, то вычтобы сделать это:

 int sum = std::accumulate(vints.begin(),vints.end(),0);

Итак, мое предложение было бы таково: возьмите в привычку использовать итераторы, так как это дает вам единообразие и постепенно позволяет вам освоиться с философией итераторов.Это дает ощущение щедрости!

0 голосов
/ 15 февраля 2011

Я стараюсь максимально скрыть базовые реализации моих контейнеров.

Так что в вашем примере я бы начал с использования typedef вместо прямой ссылки на вектор (позже вы поймете, почему):

typedef std::vector<string> MyStringCollection;

Затем я попытаюсь использовать конструкции, которые как можно меньше полагаются на базовую реализацию.В этом случае я хочу перебрать контейнер и использовать значения в контейнере, например:

for(MyStringCollection::iterator it=mycollection.begin(); it!=mycollection.end(); ++it)
   {
   // use *it
   } 

С помощью typedef пользователи вашей коллекции должны использовать только MyStringCollection::iterator без необходимости знатьчто такое MyStringCollection.

Обратите внимание, что в C ++ 0x вы можете использовать auto, что еще короче (что делает мой аргумент для typedef менее актуальным).

Преимуществотеперь стало довольно легко изменить MyStringCollection с std :: vector на std :: list.Если по соображениям производительности вы решили, что список лучше подходит, вам нужно только:

  • Заменить typedef с std :: vector на std :: list
  • Иметьбыстрый просмотр всех мест, где используется MyStringCollection (это будет легче найти, чем поискать все применения std :: vector
0 голосов
/ 15 февраля 2011

от Meyers "Effective STL", пункт 43.

"Предпочитать вызовы алгоритмов рукописным циклам"

  • алгоритмы часто более эффективны, чем программисты циклов
  • запись циклов более подвержена ошибкам
  • код алгоритма легче читать

использовать алгоритмы с итераторами как можно чаще.

std::for_each(myvec.begin(), myvec.end(), [](const string& s) {
   /* your code here */
});
0 голосов
/ 15 февраля 2011

Это зависит от того, нужно ли вам знать положение элемента в его контейнере при выполнении тела цикла.Если вы это сделаете, вам нужно использовать вторую форму.Если нет, используйте первое, потому что оно более общее и, следовательно, более гибкое;вы можете изменить тип myvec на любой, который поддерживает итераторы, даже если он не поддерживает произвольный доступ.

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