#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
.