15 Special member functions [special]

15.8 Copying and moving class objects [class.copy]

15.8.1 Copy/move constructors [class.copy.ctor]

Конструктор без шаблона для класса X является ,copy constructor если ее первый параметр имеет тип X&, const X&, volatile X& или const volatile X&, и либо нет других параметров или также все другие параметры default arguments. [ Example: X​::​X(const X&) и X​::​X(X&,int=1) являются конструкторами копирования.

struct X {
  X(int);
  X(const X&, int = 1);
};
X a(1);             // calls X(int);
X b(a, 0);          // calls X(const X&, int);
X c = b;            // calls X(const X&, int);

end example]

Конструктор без шаблона для класса X является , move constructor если ее первый параметр имеет тип X&&, const X&&, volatile X&&или const volatile X&&, и либо нет других параметров или также все другие параметры default arguments. [ Example: Y​::​Y(Y&&) - конструктор перемещения.

struct Y {
  Y(const Y&);
  Y(Y&&);
};
extern Y f(int);
Y d(f(1));          // calls Y(Y&&)
Y e = d;            // calls Y(const Y&)

end example]

[ Note: Все формы конструктора копирования / перемещения могут быть объявлены для класса. [Example:

struct X {
  X(const X&);
  X(X&);            // OK
  X(X&&);
  X(const X&&);     // OK, but possibly not sensible
};

end example] ]end note

[ Note: Если класс X имеет только конструктор копирования с параметром типа X&, инициализатор типа const X или volatile X не может инициализировать объект типа (возможно, с квалификацией cv) X. [Example:

struct X {
  X();              // default constructor
  X(X&);            // copy constructor with a non-const parameter
};
const X cx;
X x = cx;           // error: X​::​X(X&) cannot copy cx into x

end example] ]end note

Объявление конструктора для класса X неправильно сформировано, если его первый параметр имеет тип (необязательно cv-квалифицированный) X и либо нет других параметров, либо все другие параметры имеют аргументы по умолчанию. Шаблон функции-члена никогда не создается для создания такой сигнатуры конструктора. [Example:

struct S {
  template<typename T> S(T);
  S();
};

S g;

void h() {
  S a(g);           // does not instantiate the member template to produce S​::​S<S>(S);
                    // uses the implicitly declared copy constructor
}

end example]

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

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

X::X(const X&)

если каждый потенциально сконструированный подобъект типа класса M (или его массива) имеет конструктор копирования, первый параметр которого имеет тип const M& или const volatile M&.119 В противном случае неявно объявленный конструктор копии будет иметь вид

X::X(X&)

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

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

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

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

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

[ Note: Когда конструктор перемещения не объявляется неявно или не предоставляется явно, выражения, которые в противном случае вызвали бы конструктор перемещения, могут вместо этого вызывать конструктор копирования. ] end note

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

X::X(X&&)

Неявно объявленный конструктор копирования / перемещения является inline public членом своего класса. Конструктор копирования / перемещения по умолчанию для класса X определяется так, как deleted если бы он X имел:

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

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

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

  • для конструктора копирования - нестатический член данных ссылочного типа rvalue.

Конструктор перемещения по умолчанию, который определен как удаленный, игнорируется разрешением перегрузки ([over.match], [over.over]). [ Note: В противном случае удаленный конструктор перемещения помешал бы инициализации из rvalue, который вместо этого может использовать конструктор копирования. ]end note

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

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

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

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

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

Конструктор копирования / перемещения, который установлен по умолчанию и не определен как удаленный, - implicitly defined это если он есть odr-used или когда он явно задан по умолчанию после его первого объявления. [ Note: Конструктор копирования / перемещения определяется неявно, даже если реализация опускает его odr-use ([class.temporary]). ] Если неявно определенный конструктор удовлетворяет требованиям a , то неявно определенный конструктор будет .end noteconstexpr constructor constexpr

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

Неявно определенный конструктор копирования / перемещения для класса, неX являющегося объединением, выполняет поэлементное копирование / перемещение его баз и членов. [ Note: Инициализаторы нестатических элементов данных по умолчанию игнорируются. См. Также пример в [class.base.init]. ] Порядок инициализации такой же, как порядок инициализации баз и членов в определяемом пользователем конструкторе (см. ). Пусть будет либо параметром конструктора, либо, для конструктора перемещения, значением xvalue, относящимся к параметру. Каждый базовый или нестатический член данных копируется / перемещается в соответствии с его типом: end note [class.base.init] x

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

  • если член m имеет ссылочный тип rvalue T&&, он инициализируется напрямую с помощью static_­cast<T&&>(x.m);

  • в противном случае база или член инициализируются напрямую соответствующей базой или членом x.

Подобъекты виртуального базового класса должны быть инициализированы только один раз неявно определенным конструктором копирования / перемещения (см [class.base.init]. Раздел "Ресурсы" ).

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

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