Нужно ли вектору (контейнеру) использовать «распределитель»? - PullRequest
1 голос
/ 31 января 2012

Я смотрел, как создаются пользовательские контейнеры, такие как контейнер eastl и несколько других моделей, и вижу, что все они используют «распределитель», во многом как std::vector делает с std::allocator.Это заставило меня задуматься, почему новые реализации векторного контейнера используют распределитель, когда они обычно имеют базовое переопределение управления памятью для new и delete?

Ответы [ 3 ]

4 голосов
/ 31 января 2012

Возможность замены operator new() и operator delete() (и их версий массива) на уровне программы может быть достаточной для небольших программ.Если у вас есть программы, состоящие из многих миллионов строк кода, работающих с разными потоками, это совсем не подходит.Вы часто хотите или даже нуждаетесь в лучшем контроле.Чтобы сделать использование пользовательских распределителей эффективным, вам также необходимо иметь возможность распределять подобъекты, используя те же объекты, что и внешний распределитель.

Например, рассмотрите использование области памяти, которая будет использоваться при ответе на запрос вкакой-то сервер, который, вероятно, работает с несколькими потоками.Получение памяти из operator new(), вероятно, довольно дорого, поскольку требует выделения блокировки и поиска подходящего куска памяти в куче, которая становится все более фрагментированной.Чтобы избежать этого, вам просто нужно выделить несколько кусков памяти (в идеале - один, но вы можете заранее не знать необходимый размер) и поместить все объекты туда.Распределитель может сделать это.Для этого вам нужно проинформировать все сущности, выделяющие память, об этом фрагменте памяти, т.е. вам нужно передать распределитель всему, что может выделить память.Если вы выделяете, например, std::vector<std::string, A>, то объекты std::string должны знать о распределителе: просто указать std::vector<std::string, A>, где и как выделить память, недостаточно, чтобы избежать большинства выделений памяти: вам также нужно сообщить это std::string (ну, на самом деле std::basic_string<char, std::char_traits<char>, B> для подходящего типа распределителя B, который относится к A).

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

1 голос
/ 31 января 2012

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

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

0 голосов
/ 31 января 2012

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

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

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

...