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

Почему деструктор отключает генерацию неявных методов перемещения?

Я пытался понять, что говорит правило 0, читая этот блог. IMO, он говорит, что если вы объявите своего собственного деструктора, тогда не забудьте сделать конструктор перемещения и перенести назначение по умолчанию.

Пример:

class Widget {
public:
  ~Widget();         // temporary destructor
  ...                // no copy or move functions
};

"Добавление деструктора имеет побочный эффект отключения генерация функций перемещения, но поскольку Widget является скопируемым, все код, который используется для генерации ходов, теперь будет генерировать копии. В другими словами, добавление деструктора в класс вызвало предположительно-эффективные шаги, которые должны быть заменены молча предположительно менее эффективных копий".

Вышеприведенный текст Скотта Мейерса, внутри цитат, вызывает у меня некоторые вопросы:

  • Почему объявление деструктора скрывает семантику перемещения?
  • Объявляет/определяет деструктор только скрывает семантику перемещения или копирует конструктор и копирование, а также скрывает семантику перемещения?
4b9b3361

Ответ 1

"Правило нуля" на самом деле о чем-то другом, кроме того, что генерируются специальные функции-члены и когда. Речь идет о некотором отношении к классу дизайна. Он призывает вас ответить на вопрос:

Поддерживает ли мой класс ресурсы?

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

Это частный случай более общего принципа одиночной ответственности.

Когда вы примените его, вы сразу увидите, что для классов управления ресурсами вам нужно будет вручную определить конструктор перемещения, переместить назначение и деструктор (редко вам понадобятся операции копирования). А для классов, не относящихся к ресурсам, вам не нужно (и на самом деле вы, вероятно, не должны) объявить о любом из: move ctor/assign, copy ctor/assign, destructor.

Следовательно, "ноль" в названии: когда вы разделяете классы на управление ресурсами и другие, в "других" вам нужно предоставить нулевые специальные функции-члены (они будут автоматически автогенерированы.

В С++ есть правила, какое определение (специальной функции-члена) запрещает другие определения, но они только отвлекают вас от понимания ядра правила нуля.

Для получения дополнительной информации см.

Ответ 2

Почти всегда, если у вас есть деструктор (который "что-то делает" ), вы должны следовать "правилу из трех", которое затем становится "правилом пяти", если вы хотите переместить семантику.

Если ваш деструктор пуст, тогда он не нужен. Таким образом, подразумевается, что непустой деструктор (потому что у вас его нет, если он не нужен!), Тогда вам также нужно сделать то же самое в операциях копирования и присваивания, и, предположительно, переместить построение и переместить назначение потребуется "что-то делать", а не просто передавать фактическое содержимое через.

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

Ответ 3

объявляет/задает Dtor только скрыть семантику перемещения или скопировать ctor/copy, а также скрыть семантику перемещения?

Если для класса не предусмотрены определенные конструкторы перемещения , все это верно:

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

тогда компилятор объявит конструктор перемещения как неявный встроенный публичный член своего класса с signature T::T(T&&).

Таким образом, да, объявляющий конструктор копирования или оператор присваивания, также скрывает неявно объявленный конструктор перемещения.