В каком сценарии я использую конкретный контейнер STL?


Я читал о контейнерах STL в своей книге на C++, в частности, раздел о STL и его контейнерах. Теперь я понимаю, что у каждого из них есть свои специфические свойства, и я близок к тому, чтобы запомнить их все... Но я пока не понимаю, в каком сценарии используется каждый из них.

каково объяснение? Пример кода гораздо предпочтительнее.

8 163

8 ответов:

это шпаргалка обеспечивает довольно хорошее резюме различных контейнеров.

см. блок-схему внизу в качестве руководства для использования в различных сценариях использования:

http://linuxsoftware.co.nz/containerchoice.png

создано Дэвид Мур и лицензионный CC BY-SA 3.0

вот блок-схема, вдохновленная версией Дэвида Мура (см. выше), которую я создал, которая обновлена (в основном) с новым стандартом (C++11). Это только мой личный взгляд на это, это не бесспорно, но я подумал, что это может быть полезно для этого обсуждения:

enter image description here

простой ответ: используйте vector для всего, если у вас нет реальной причины поступать иначе.

когда вы находите случай, когда вы думаете: "Gee, vector не работает хорошо здесь из-за X", идите на основе X.

смотреть на эффективное использование STL Скотт Мейерс. Это хорошо объясняет, как использовать STL.

Если вы хотите сохранить определенное/неопределенное количество объектов, и вы никогда не собираетесь удалять, то вектор является то, что вы хотите. Это замена по умолчанию для массива C, и он работает как один, но не переполнение. Вы можете установить его размер заранее, а также с резервом ().

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

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

Если у вас много пар ключ-значение, и вы хотите отсортировать их по ключ, то карта полезна...но он будет содержать только одно значение на один ключ. Если вам нужно более одного значения на ключ, вы можете иметь вектор/список в качестве значения на карте или использовать multimap.

Это не в STL, но это в обновлении TR1 для STL: если у вас есть много пар ключ-значение, которые вы собираетесь искать по ключу, и вы не заботитесь об их порядке, вы можете использовать хэш - который является tr1::unordered_map. Я использовал его с Visual C++ 7.1, где он был вызван stdext:: hash_map. Он имеет поиск O(1) вместо поиска O (log n) для map.

все зависит от того, что вы хотите хранить и что вы хотите сделать с контейнером. Вот некоторые (очень неисчерпывающие) примеры для классов контейнеров, которые я обычно использую:

vector: компактная компоновка с минимальными или нулевыми затратами памяти на каждый содержащийся объект. Эффективный для итерации. Добавление, вставка и стирание могут быть дорогостоящими, особенно для сложных объектов. Дешево найти содержащий объект по индексу, например myVector[10]. Используйте там, где вы бы использовали массив в C. Хорошо, когда у вас есть много простых объектов (например, int). Не забудьте использовать reserve() перед добавлением большого количества объектов в контейнер.

list: небольшие накладные расходы памяти на один содержащийся объект. Эффективный для итерации. Добавить, вставить и стереть дешево. Используйте там, где вы бы использовали связанный список в C.

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

mapmultimap): значительные затраты памяти на каждый содержащийся объект. Используйте там, где вы хотите хранить пары ключ-значение и быстро искать значения по ключу.

на схеме шпаргалка предложенный здан обеспечивает более исчерпывающее руководство.

важный момент, только кратко упомянутый до сих пор, заключается в том, что если вам требуется непрерывная память (например, массив C дает), то вы можете использовать только vector,array или string.

использовать array если размер известен во время компиляции.

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

использовать vector во всех остальных случаях (vector должен быть выбор контейнера по умолчанию в большинстве случаев в любом случае.)

со всеми тремя из них вы можете использовать data() функция-член, чтобы получить указатель на первый элемент контейнера.

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

class CollectionOfFoo {
    Collection<Foo*> foos;
    .. delegate methods specifically 
}

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

переход к выбору идеальной структуры данных для задания:

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

O (1), O(lg N), O (N) и др.

вы по существу должны принять лучшее предположение, на котором операции будут выполняться больше всего, и использовать структуру данных, которая имеет эту операцию как O(1).

просто, не так ли (-:

Я остановился на Микаэль Перссон фантастическая схема. Я добавил некоторые категории контейнеров, контейнер массива и некоторые заметки. Если вам нужна ваша собственная копия,здесь Это рисунок Google. Спасибо, Микаэль за проделанную работу! C++ Container Picker