Топ контрибуторов
loading
loading
Знаете ли Вы, что

Вы можете подписаться на RSS ленту новых тестов сервиса Quizful, в том числе и отдельно по каждой категории

Лента обновлений
ссылка Oct 22 23:24
Комментарий от alexcei88:
В вопросе переменная s даже не выводиться, а выводитьс...
ссылка Oct 22 17:46
Комментарий от AlexFurm:
Это UB, так можно вызывать только статические функции ч...
ссылка Oct 22 17:43
Комментарий от AlexFurm:
Любые битовые операции с signed это UB
ссылка Oct 21 20:30
Комментарий от yoori:
Любой вариант скомпилируется если компилировать не в конеч...
ссылка Oct 21 16:53
Добавлен вопрос в тест QA (Quality Assurance)
Статистика

Тестов: 153, вопросов: 8596. Пройдено: 443367 / 2177508.

STL code snippets (правила использования STL в c++)

head tail Статья
категория
C++
дата15.05.2009
авторanalizer
голосов14

Многие говорят что умеют, на деле умеют не многие

Рекомендуемая литература:

К чему эпиграф?

К тому что многие C++ программисты говорят что умеют пользоваться контейнерами из библиотеки STL. На деле же приходится сталкиваться и с итераторами объявленными вне for и с дополнительным итераторами при удалении элемента из листа. На самом деле есть простые правила которым нужно следовать при обходе стандартных контейнеров:

  1. Не обходите вектор путём перебора его элементов по индексам, вы запросто можете потерять один из добавленных элементов. Используйте итераторы.
  2. Если не собираетесь менять значения элементов или же удалять их - используйте const_iterator. Так вы оставите себе и другим напоминание о том что контейнер нельзя менять.
  3. Никогда не сравнивайте итераторы при помощи операторов "больше" (>) или "меньше" (<), проверяйте их только на равенство (==) и неравенство (!=), стандарт не гарантирует что итератор указывающий на элемент последовательности обязательно должен быть "меньше" итератора элемента который находится в последовательности после данного.
  4. Если разницы нет - предпочитайте префиксный инкремент/декремент постфиксному (это касается не только стандартных контейнеров и итераторов). Префиксные операторы возвращают ссылку на элемент, а постфиксные - копию объекта, причём копирование объекта может занимать порой значительное время.
  5. Если не собираетесь менять количество элементов - объявляйте итераторы начала и конца контейнера в первой секции цикла for. Не надо этими итераторами засорять внешнее пространство имён. Например можно делать так:
    for(std::list<int>::const_iterator iter=lst.begin(), end=lst.end(); iter != end; ++iter)
  6. Если собираетесь менять количество элементов - получайте итератор конца контейнера каждый раз когда проверяется условие продолжения цикла.
  7. При удалении элементов последовательности (sequences) возвращают итератор элемента следующего за удалённым (аналогично для всех контейнеров операция вставки одиночного элемента возвращает итератор вставленного элемента):
    for(std::list<int>::iterator iter=lst.begin(); iter != lst.end(); )
    {
    	if(check_condition(*iter))
    	{
    		iter = lst.erase(iter);
    	}
    	else
    	{
    		++iter;
    	}
    }
  8. По возможности, старайтесь использовать стандартные алгоритмы - это поможет избежать изобретения собственных велосипедов (у которых могут запросто оказаться квадратные колёса). Например, код выше запросто можно заменить этим (feel the difference):
    lst.remove_if(check_condition);
  9. Дополнение к пункту выше - вам не обязательно объявлять функции, которые вы собираетесь передавать в стандартные алгоритмы, в глобальной области видимости. Можно воспользоваться Boost.Lambda или же статьёй приведённой в списке рекомендуемой литературы:
    #include <boost/preprocessor/cat.hpp>
    
    #define LOCAL(R, P) \
      typedef struct { typedef R(*F) P; static R body P {
    
    #define LOCAL_END(name) \
      } } BOOST_PP_CAT(local_func_,__LINE__); \
      const BOOST_PP_CAT(local_func_,__LINE__)::F name = BOOST_PP_CAT(local_func_,__LINE__)::body
    ...
    LOCAL(bool, (int i))
    	return i & 1;
    LOCAL_END(is_odd);
    lst.remove_if(is_odd);
  10. Если вы обходите массив по индексам, индексы начинаются с нуля (самый распространённый случай) и порядок обхода неважен - обходите не от нулевого элемента к последнему, а от последнего к нулевому (сравнение числа с нулём требует меньше времени чем с какой-либо другой константой):
    int a[10];
    for(unsigned i = 10; i--; )
    	...

Я понимаю, эти правила звучат ультимативно, но из своего опыта могу сказать что если вы будете этим правилам следовать, то хуже ваш c++ код точно не станет.

Статья получилась очень короткая, но кто понял о чём правила выше - тот возьмёт на вооружение, кто уже использовал - даст почитать другим.

----

Дмитрий analizer Потапов, апрель 2009

Если Вам понравилась статья, проголосуйте за нее

Голосов: 14  loading...
sgauStudent   clumsy   md6   misha91   alexis112   Sekt104   ligth1987   valyala   Shved90   serj   admin   turanga_leela   Probleskovy   Riddler