Подтвердить что ты не робот

Сменил ли С++ 11 требования к элементам контейнеров STL и как?

Недавно я удивлен тем фактом, что std::unique_ptr является приемлемым для элементов контейнеров STL, поскольку я думал, что эти элементы необходимы для предоставления функций ниже (эта страница говорит то же самое):

  • открытый конструктор по умолчанию без аргументов
  • конструктор общих копий
  • Функция оператора присваивания публичных копий
  • публичный деструктор

Но std::unique_ptr не копируется, чтобы сделать указатель, который он содержит, принадлежащий одному объекту, что противоречит вышеприведенным требованиям.

Стандарт изменил требования? Если да, то каковы изменения? Возможно, достаточно подвижных объектов или скопированных? Я искал в Интернете, изменились ли требования с С++ 11, но я не могу найти страницу, которая мне помогает...

4b9b3361

Ответ 1

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

std::vector обычно требует, чтобы его члены были MoveConstructible и MoveAssignable. Существует множество функций-членов std::vector, которые предъявляют более строгие требования. vector::push_back требуется Move или CopyConstructible (в зависимости от того, передаете ли вы rvalue или lvalue), но для нового vector::emplace_back требуется только, чтобы был доступный конструктор, который принимает заданные параметры (в дополнение к базовому требованию). Очевидно, что любая попытка вызвать конструктор/назначение копии vector потребует, чтобы тип был CopyConstructible (то есть: вы не можете скопировать a std::vector<unique_ptr>).

Аналогично, большинство других контейнеров уменьшили ограничения на тип. Они также имеют функции-члены emplace, которые позволяют вам создавать элементы на месте, а также функции ввода l/rvalue. Это означает, что вам не нужно копировать значения; вы можете переместить их или создать их на месте.

Ни один из конструкторов или деструкторов не должен быть общедоступным; все это происходит через вызовы allocator_traits<Allocator>::construct. Поэтому, если вы предоставите распределитель, вы можете сделать ваши конструкторы/деструкторы частными. Ну, если ваш класс распределителя может получить к ним доступ, конечно.

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