2015-02-16 2 views
1

В std :: vectors push_back implemetation, когда size() == capacity(), часть, которую она выделяет в два раза больше места и копирует элементы старого, я хочу спросить, способ копирования?<vector> реализация push_back internal

+0

Не могли бы вы сделать свой вопрос более ясным? Вы спрашиваете, как векторы копируют старые элементы, и вы хотите сделать то же самое, или что? – therainmaker

+0

Я не хочу делать то же самое, я хочу знать, как это сделать вектор? –

+0

Затем просто найдите файл заголовка и посмотрите, как он это делает? Мой ответ дает варианты того, как это сделать «наиболее эффективно». Он не описывает, что делает ваша реализация std :: vector <>, скорее всего. – BitTickler

ответ

1

Звучит немного так, как если бы вы хотели реализовать std::vector<>.
Наиболее эффективным способом является предотвращение перераспределения в первую очередь, что часто, но не всегда возможно.

Если у вас есть предварительные сведения о количестве предметов, вы будете push_back() дальше, вы можете использовать std::vector<>::reserve() и вообще избегать перераспределения.

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

Причина, по которой эта функция может быть полезна, заключается в том, что есть хорошая вероятность того, что блок данных в куче еще остается за блоком данных. realloc() - единственная функция, которая позволяет избежать 100% времени перемещения данных, расширяя размер блоков кучи, не касаясь данных вообще, если есть достаточно места для этого.

Недостаток использования realloc() заключается в том, что реализация «специальной производительности» отказалась бы от концепции распределителей, а также не справилась бы с типами элементов, которые требуют вызовов конструктора кода и т. Д. Поэтому вам лучше не называть векторный вектор, а что-то вроде «SimpleDataVector» и, возможно, создать какой-то механизм обнаружения неправильного использования.

+0

Это работает только для тривиальных типов. – Deduplicator

+0

Не, если в реализации также используется новое размещение и т. Д. – BitTickler

+0

Как следует «realloc» знать, какое размещение - новое для использования? – Deduplicator

2

Это не указано в стандарте, но оставлено для реализации. Таким образом, разные версии библиотеки C++ будут делать это по-другому. Тем не менее, allocator из vector должен использоваться для любых выделений и де-распределения (следовательно, не используется realloc()).

В стандарте указано, что если объекты можно перемещать (вместо копирования), то их следует перемещать (начиная с C++ 11). Как правило, выделяется новый блок необработанной памяти, обычно в два раза превышающий размер предыдущего, а затем элементы перемещаются (или копируются и уничтожаются) из предыдущего в старый. Для общего случая это перемещение/копирование должно выполняться один за другим (поскольку в противном случае целостность перемещений/копирование не может быть гарантирована без знания внутренних элементов соответствующих конструкторов перемещения/копирования). Конечно, для pod (= простых старых данных) возможны оптимизации типов с помощью std::memcpy() (и, скорее всего, реализованы).

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

+0

Правильно, я забыл об этих отложенных распределителях. Когда я сделал свои внедренные векторы-заменители классов с некоторыми дополнительными материалами, я вообще не добавлял распределители. – BitTickler

Смежные вопросы