15 Special member functions [special]

15.8 Copying and moving class objects [class.copy]

15.8.2 Copy/move assignment operator [class.copy.assign]

Пользователь объявленной copy оператор присваивания X​::​operator= не является членом статической функцией не-шаблона класса X ровно с одним параметром типа X, X&, const X&, volatile X& или const volatile X&.120 [ Note: Должен быть объявлен перегруженный оператор присваивания, имеющий только один параметр; см [over.ass]. ] [ Для класса может быть объявлено более одной формы оператора присваивания копии. ] [ Если у класса есть только оператор присваивания копии с параметром типа , выражение типа const не может быть присвоено объекту типа . [end noteNote: end noteNote: XX&XXExample:

struct X {
  X();
  X& operator=(X&);
};
const X cx;
X x;
void f() {
  x = cx;           // error: X​::​operator=(X&) cannot assign cx into x
}

end example] ]end note

Если в определении класса явно не объявляется оператор присваивания копии, он объявляется implicitly. Если определение класса объявляет конструктор перемещения или оператор присваивания перемещения, неявно объявленный оператор присваивания копии определяется как удаленный; в противном случае он определяется как defaulted. Последний случай считается устаревшим, если в классе есть объявленный пользователем конструктор копии или объявленный пользователем деструктор. Неявно объявленный оператор присваивания копии для класса X будет иметь вид

X& X::operator=(const X&)

если

  • каждый непосредственный базовый класс B из X имеет оператор присваивания , копирование параметры которого имеет типа const B&, const volatile B& или B, и

  • для всех нестатических членов данных, X которые относятся к типу класса M (или его массиву), каждый такой тип класса имеет оператор присваивания копии, параметр которого имеет тип const M&, const volatile M& или M.121

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

X& X::operator=(X&)

Пользователь объявленной move оператор присваивания X​::​operator= не является членом статической функцией не-шаблона класса X ровно с одним параметром типа X&&, const X&&, volatile X&&, или const volatile X&&. [ Note: Должен быть объявлен перегруженный оператор присваивания, имеющий только один параметр; см [over.ass]. ] [ Для класса может быть объявлено более одной формы оператора присваивания перемещения. ] end noteNote: end note

Если в определении класса X явно не объявляется оператор присваивания перемещения, он будет неявно объявлен как принятый по умолчанию тогда и только тогда, когда

  • X не имеет объявленного пользователем конструктора копирования,

  • X не имеет конструктора перемещения, объявленного пользователем,

  • X не имеет объявленного пользователем оператора присваивания копии, и

  • X не имеет деструктора, объявленного пользователем.

[ Example: Определение класса

struct S {
  int a;
  S& operator=(const S&) = default;
};

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

struct S {
  int a;
  S& operator=(const S&) = default;
  S& operator=(S&&) = default;
};

end example]

Неявно объявленный оператор присваивания перемещения для класса X будет иметь вид

X& X::operator=(X&&);

Неявно объявленный оператор присваивания копирования / перемещения для класса X имеет тип возвращаемого значения X&; он возвращает объект, для которого вызывается оператор присваивания, то есть объект, которому назначен. Неявно объявленный оператор присваивания копирования / перемещения является inline public членом своего класса.

Оператор присваивания копирования / перемещения по умолчанию для класса X определяется как удаленный, если X он:

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

  • нестатический член данных const неклассового типа (или его массив), или

  • нестатический член данных ссылочного типа, или

  • прямой нестатический член данных типа класса M (или его массива) или прямой базовый класс, M который не может быть скопирован / перемещен, поскольку overload resolutionв применении к Mсоответствующему оператору присваивания find приводит к неоднозначности или к функции, которая удаляется или недоступна из оператора присваивания по умолчанию.

Оператор присваивания перемещения по умолчанию, который определен как удаленный, игнорируется разрешением перегрузки ([over.match], [over.over]).

Поскольку оператор присваивания копирования / перемещения неявно объявляется для класса, если он не объявлен пользователем, оператор присваивания копирования / перемещения базового класса всегда скрывается соответствующим оператором присваивания производного класса ([over.ass]). A, using-declarationкоторый переносит из базового класса оператор присваивания с типом параметра, который может быть типом оператора присваивания копирования / перемещения для производного класса, не считается явным объявлением такого оператора и не подавляет неявное объявление производного оператор класса; оператор, представленный с помощью using-declaration , скрыт неявно объявленным оператором в производном классе.

Оператор присваивания копирования / перемещения для класса X является тривиальным, если он не предоставляется пользователем и если:

  • класс X не имеет virtual functions и нет virtual base classes, и

  • оператор присваивания, выбранный для копирования / перемещения каждого прямого подобъекта базового класса, является тривиальным, и

  • для каждого нестатического элемента данных X , принадлежащего к типу класса (или его массиву), оператор присваивания, выбранный для копирования / перемещения этого члена, является тривиальным;

в противном случае используется оператор присваивания копирования / перемещения non-trivial.

Оператор присваивания копирования / перемещения для класса, X который установлен по умолчанию и не определен как удаленный, - implicitly defined это когда он есть odr-used (например, когда он выбран разрешением перегрузки для назначения объекту своего типа класса) или когда он явно используется по умолчанию после его первого декларация. Неявно определенный оператор присваивания копирования / перемещения - это constexpr если

  • X это буквальный тип, а

  • оператор присваивания, выбранный для копирования / перемещения каждого прямого подобъекта базового класса, является функцией constexpr, и

  • для каждого нестатического члена данных, X имеющего тип класса (или его массив), оператор присваивания, выбранный для копирования / перемещения этого члена, является функцией constexpr.

Перед тем как оператор присваивания копирования / перемещения по умолчанию для класса будет неявно определен, все операторы присваивания копирования / перемещения, не предоставляемые пользователем, для его прямых базовых классов и его нестатических элементов данных должны быть неявно определены. [ Note: Неявно объявленный оператор присваивания копирования / перемещения имеет подразумеваемый exception specification. ]end note

Неявно определенный оператор присваивания копирования / перемещения для класса, не являющегося объединением, X выполняет поэлементное присвоение его подобъектов копированию / перемещению. Первыми X назначаются прямые базовые классы в порядке их объявления в base-specifier-list, а затемX назначаются непосредственные нестатические члены данных в том порядке, в котором они были объявлены в определении класса. Пусть x будет либо параметром функции, либо, для оператора перемещения, значением x, относящимся к параметру. Каждому подобъекту присваивается способ, соответствующий его типу:

  • если подобъект имеет тип класса, как если бы при вызове operator= с подобъектом в качестве выражения объекта и соответствующим подобъектом x в качестве единственного аргумента функции (как если бы посредством явной квалификации; то есть игнорирование любых возможных виртуальных замещающих функций в более производных классы);

  • если подобъект является массивом, каждому элементу присваивается способ, соответствующий типу элемента;

  • если подобъект скалярного типа, используется встроенный оператор присваивания.

Не указано, назначаются ли подобъекты, представляющие виртуальные базовые классы, более одного раза неявно определенным оператором присваивания копирования / перемещения. [Example:

struct V { };
struct A : virtual V { };
struct B : virtual V { };
struct C : B, A { };

Не указано,V назначается ли подобъект виртуального базового класса дважды неявно определенным оператором присваивания копирования / перемещения для C. ]end example

Неявно определенный оператор копирующего присваивания для союзной X копирует object representation из X.

Поскольку оператор присваивания шаблона или оператор присваивания, принимающий параметр ссылки rvalue, никогда не является оператором присваивания копии, наличие такого оператора присваивания не подавляет неявное объявление оператора присваивания копии. Такие операторы присваивания участвуют в разрешении перегрузки с другими операторами присваивания, включая операторы присваивания копий, и, если они выбраны, будут использоваться для назначения объекта.

Это означает, что ссылочный параметр неявно объявленного оператора присваивания копии не может связываться с volatile lvalue; см [diff.special].