2013-09-19 4 views
4

я прочитал в общепринятом ответ here что:Является ли явное перемещение ctor устранением неявной копии ctor?

[а] конструктор копирования и копирования оператор присваивания не будет сгенерирован для класса, который явно декларирует MOVE конструктору или оператор присваивания шаг

Я замечаю (g ++ 4.7.2), что если вы определяете конструктор перемещения, он будет использоваться, например, с push_back(), тогда как если вы все сделаете, то это будет конструктор копирования, вы не получите неявный конструктор перемещения - - вы получите сообщение об ошибке. [... которая заставляет меня задаться вопросом, какой из них (перемещение или копирование) фактически используется, если вы ничего не делаете явно ...]

Однако this online reference не делает те же заверяла о копии конструктор не неявно определяется при определении конструктора перемещения.

Итак, мой вопрос в том, является ли первая цитата гарантированной стандартом (включая "или")? Я бы предпочел, чтобы некоторые классы, которые нуждались в явном деструкторе, выполнили «правило пяти» с помощью только конструктора перемещения и оператора (удаляемого) перемещения и полагались на неявные методы копирования , а не. Если я не могу положиться на это, тогда мне придется явно указать =delete, но это много потенциально избыточных вещей.

+1

В этом онлайновом справочнике говорится, что «неявный конструктор копирования для класса T не будет сгенерирован, если выполнено одно из следующих условий:» ... «T имеет определяемый пользователем конструктор перемещения или операцию перемещения оператора». Возможно, формулировка может потребовать полировки ... теперь она говорит: «определяется как удаленный, если» – Cubbi

ответ

6

Итак, мой вопрос в том, является ли первая цитата гарантированной стандартом (включая "или")?

Да, ваша первая цитата гарантирована стандартом.

Цитата от стандарта (проект n3690):

12,8 Копирование и перемещение объектов класса [class.copy]

7/Если определение класса не явно объявить конструктор копирования, одно объявляется неявно. Если определение класса объявляет конструктор перемещения или перемещает оператор присваивания, неявно объявленный конструктор копирования определяется как удаленный; в противном случае он определяется как дефолт (8.4). Последний случай устарел, если класс имеет пользовательский оператор назначения копирования или объявленный пользователем деструктор.

2

Интересное продолжение - почему?

В C++ 98 был Rule of Three:

Если вы определить какой-либо один из следующих вариантов, вы должны определить все три:

  • деструктор
  • конструктор копирования
  • копию оператор присвоения

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

Когда C++ 11 появился за углом, многие люди утверждали, что эта проблема была вызвана определением по умолчанию, предоставленным языком, и что было бы лучше, оглядываясь назад, не предоставлять их по умолчанию , Конечно, C предоставляет их по умолчанию (для struct), поэтому ...

... некоторые предположили, что на самом деле правило правил может быть исполнено компилятором; или, по крайней мере, поскольку изменение существующего поведения может привести к поломке существующего кода, что кулон правила 3 ​​может быть принудительно применен компилятором всякий раз, когда речь идет о конструкторе перемещения или перемещении оператора присваивания (который гарантирует новый код C++ 11).

Правило Пяти:

Если вы определить какой-либо один из следующих действий, вы должны определить все пять:

  • деструктор
  • шаг конструктора
  • оператор присваивания шаг
  • копировальный аппарат
  • назначение копии Оператор

, таким образом, почти полностью реализован как:

  • если определить конструктор перемещения или перемещения оператора присваивания, остальные 4 метода неявно удаляются (если вы не предоставите их)
  • если вы определяете деструктор, конструктор копирования или оператор присваивания копии, конструктор перемещения и оператор назначения перемещения неявно удаляются (если вы не предоставите их)

второе утверждение немного неполно для соображений обратной совместимости с существующим кодом C++ 98 (который должен компилироваться как C++ 11 без изменения поведения).

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