Каково обычное соглашение для именования и использования итераторов в C ++? - PullRequest
8 голосов
/ 30 сентября 2010

Я чувствую, что я непрофессионал в том, как я называю и использую итераторы. Под этим я подразумеваю, что я «чувствую», что должен называть их как-то иначе, но я всегда называю их по префиксу «it_», и через некоторое время в длинной функции имена начинают выглядеть одинаково .

Кроме того, мне всегда интересно, делаю ли я что-то «странное», чему я научился только потому, что не знал лучше. Например, если бы я перебирал карту для отображения всех ее пар ключ / значение, я сделал бы это:

map<int, int>::const_iterator it = layout.begin();
for (; it != layout.end(); ++it)
{
   cout << it->first << ":\t" << it->second << "\n";
}

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

Ответы [ 6 ]

4 голосов
/ 30 сентября 2010

Я стараюсь объявлять итераторы внутри цикла for настолько, насколько это возможно, чтобы область действия идентификатора итератора была минимальной.

Во-первых, я typedef имен "длинных" типов для«короче» и многократно используемые:

typedef std::map< int, int > IntMap;
typedef IntMap::const_iterator IntMapConstIter;

Затем я делаю

for( IntMapConstIter it = layout.begin(); it != layout.end(); ++it ) {
    ....
}
2 голосов
/ 30 сентября 2010

Я почти уверен, что никакие соглашения не выходят за рамки стиля в этом вопросе.Я считаю, что самая важная часть именования итераторов находится во второй части (учитывая, что вы решили добавить префикс, должен ли он быть "it" или "iter_" или что-то еще).Тщательно выбирайте вторую часть, как и для любой другой переменной, и все будет в порядке.

2 голосов
/ 30 сентября 2010

Я делаю это следующим образом

for (map<int, int>::const_iterator it = layout.begin();
     it != layout.end(); ++it)
{
    cout << it->first << ":\t" << it->second << "\n";
}

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

1 голос
/ 30 сентября 2010

Я не видел ни одного канонического цикла.

Стоимость создания iterator указана равной O(1) (по отношению к размеру контейнера), но это может стоить, особенно если активированы определенные параметры отладки.

Следовательно, вызов end на каждой итерации цикла бесполезен.

Таким образом, канонический способ написать цикл for состоит в том, чтобы вычислить как it, так и end в первом операторе.

typedef std::map<int,int> LayoutType;

for (LayoutType::const_iterator it = layout.begin(), end = layout.end();
     it != end; ++it)
{
  // ...
}

Я обычно typedef мой контейнер, но, честно говоря, нет смысла в typedefing итераторе, он уже доступен в контейнере, и введение слишком большого количества синонимов не помогает.

Кроме того, это может быть личной причудой, но я предпочитаю указывать функцию , а не type , когда я представляю typedef . Тип может измениться в последующем рефакторинге, функция не изменится (по крайней мере, если это произойдет, это будет совсем не то же самое, поэтому потребуется полная перезапись).

Например, что, если вы вдруг предпочли: typedef std::unordered_map<int,int> LayoutType? Он по-прежнему соответствует вашим потребностям, и вы, вероятно, можете оставить его без затрат на переписывание (при условии, что вы использовали typedef).

1 голос
/ 30 сентября 2010

Было бы совершенно неразумно предлагать использовать BOOST_FOREACH , а вам (в основном) забыть об итераторах?

0 голосов
/ 30 сентября 2010

Имя - наименее важная вещь для меня, если оно ясно и правильно выбрано.

Это впадает в бесконечные дебаты по именованию переменных

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