Элемент вставки контейнера STL

#c #stl

#c #stl

Вопрос:

Я изучал std::set код. Я вижу insert подпись как _Pairib insert(const value_typeamp; _Val) . Почему входной параметр передается по ссылке? Я знаю, что standardcontainers копируют свои элементы в память контейнера. Кто-нибудь знает, как это достигается? Где распределители входят в картину? Приветствуется любой небольшой код / псевдокод, который объясняет, как хранятся / вставляются элементы. Мне интересно понять, как выполняется копирование.

Ответ №1:

Распределитель является параметром шаблона. Посмотрите на определение здесь:

 template < class Key, class Compare = less<Key>,
           class Allocator = allocator<Key> > class set;
 

Если вы не укажете свой собственный распределитель, он примет распределитель по умолчанию (который, вероятно, будет просто a new ).

Вы можете использовать контейнеры STL в классах с общедоступными конструкторами копирования, деструкторами и операторами присваивания. Смотрите здесь:

Элементы, вставленные в контейнер STL, могут быть любого типа объекта, который предоставляет общедоступный конструктор копирования, общедоступный деструктор и общедоступный оператор присваивания. Деструктор может не выдавать исключение. Кроме того, ассоциативные контейнеры, такие как set и map, должны иметь определенный общедоступный оператор сравнения, который по умолчанию является operator< . Для некоторых операций с контейнерами может также потребоваться общедоступный конструктор по умолчанию и общедоступный оператор эквивалентности.

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

Комментарии:

1. итак, STL вызывает конструктор копирования пользовательского типа и создает объекты в области, которая создается распределителями?

2. Спасибо, вы знаете, как я могу сделать это на C , я имею в виду, нужно ли мне использовать placement new для достижения этой цели.

3. Вы можете перегрузить new оператора и заставить его делать все, что вы хотите. Размещение new — это еще один вариант, который полезен, если фактический класс не может быть изменен. Что касается контейнеров STL — вы можете реализовать свой собственный allocator класс для своего типа и передать его в качестве последнего параметра в шаблон. Это означает, что вы должны явно указать все предыдущие параметры (например, класс сравнения, std::less<T> , для std::set ).

4. @littleadv Я считаю, что ваш последний комментарий отменен. new Оператор является распределителем и должен возвращать только блок неинициализированной памяти. Это никоим образом не является альтернативой placement-new .

5. @David, я полагаю, что намерение OP состояло в том, чтобы контролировать распределение, и именно по этой причине существуют распределители и новые места размещения. Переопределение оператора new выполняется в соответствии с той же логикой — управление распределением. Я не уверен, что понимаю, против чего вы возражаете.

Ответ №2:

Почему входной параметр передается в качестве ссылки.

Если он будет приниматься по значению, то потребуются две копии: одна для аргумента функции, а другая для узла контейнера.

Где распределители находятся здесь, на картинке.

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

Мне интересно понять, как выполняется копирование.

Тип частного узла будет содержать копию переданного аргумента insert .