std::vector и std::list — разные контейнеры STL с отличающейся реализацией и поведением.
Когда выбирать:
std::vector почти всегда, если не нужны частые вставки/удаления в середине.std::list оправдан только при необходимости вставок/удалений в любом месте при большом объёме данных, когда перемещение элементов вектора слишком дорого.std::vector зачастую быстрее из-за локальности данных.Пример:
std::vector<int> v; v.push_back(1); v[0] = 2; // быстрый доступ по индексу std::list<int> l; l.push_back(1); // l[0] = 2; // Ошибка: у std::list нет доступа по индексу!
"Почему std::list почти не применяют в современных C++-проектах, несмотря на теоретическое преимущество при частых вставках в середину коллекции?"
Ответ:
Потому что на практике из-за многочисленных мелких аллокаций, потерь локальности данных (кэш-френдли), громоздкости структуры и плохой поддержки некоторых операций (std::list неэффективен даже для больших списков из-за потерь времени на аллокацию и деаллокацию, а замедление из-за пропусков в кэше зачастую перекрывает выигрыш по асимптотике). Кроме того, современные процессоры очень чувствительны к cache locality, поэтому даже при больших объёмах данных std::vector часто быстрее в реальных условиях.
История
В системах реального времени для хранения очереди событий выбрали std::list ради частых удалений с произвольных позиций. В результате система стала в 10 раз медленнее из-за частых обращений к heap и плохой локализации данных в памяти.
История
В графовом процессоре хранили массивы соседей в виде std::list ради вставок. Это привело к драматическому росту использования памяти и деградации L1/L2 кэшей, притом что реального профита по скорости не получили.
История
В сервисе построения отчётов каждый отчёт собирался из Linked List объектов. В стресс-тестах сервис начал "тормозить", а профилировка показала узкие места в расходах на аллокацию при работе со списками. Перешли на vector — результат улучшился в разы.