Поделиться через


Копирование конструкторов и операторов назначения копирования (C++)

Примечание.

Начиная с C++11, в языке поддерживаются два типа назначения: копирование назначения и назначение перемещения. В этой статье "присваивание" означает "присваивание копированием", если явно не указано другое. Сведения о назначении перемещения см. в разделе "Конструкторы перемещения" и "Операторы назначения перемещения" (C++).

Как при операции назначения, так и при операции инициализации выполняется копирование объектов.

  • Назначение: когда значение одного объекта назначается другому объекту, первый объект копируется во второй объект. Таким образом, этот код копирует значение b в a:

    Point a, b;
    ...
    a = b;
    
  • Инициализация: инициализация возникает при объявлении нового объекта, при передаче аргументов функции по значению или при возврате значения из функции.

Можно определить семантику копии объектов типа класса. Рассмотрим для примера такой код:

TextFile a, b;
a.Open( "FILE1.DAT" );
b.Open( "FILE2.DAT" );
b = a;

Предыдущий код может означать "копирование содержимого FILE1. DAT в FILE2. DAT или может означать "игнорировать FILE2". DAT и сделайте b второй дескриптор для FILE1.DAT". Необходимо присоединить соответствующую семантику копирования к каждому классу следующим образом:

  • Используйте оператор operator= назначения, который возвращает ссылку на тип класса и принимает один параметр, передаваемый по const ссылке, например ClassName& operator=(const ClassName& x);.

  • Используйте конструктор копирования.

Если вы не объявляете конструктор копирования, компилятор создает конструктор копирования с правильным элементом. Аналогичным образом, если вы не объявляете оператор назначения копирования, компилятор создает для вас оператор назначения мудрее элементов. Объявление конструктора копирования не подавляет оператор назначения копирования, созданный компилятором, и наоборот. При реализации одного из них рекомендуется реализовать другой. При реализации обоих значений кода ясно.

Конструктор копирования принимает аргумент типа ClassName&, где ClassName — имя класса. Рассмотрим пример.

// spec1_copying_class_objects.cpp
class Window
{
public:
    Window( const Window& );            // Declare copy constructor.
    Window& operator=(const Window& x); // Declare copy assignment.
    // ...
};

int main()
{
}

Примечание.

По возможности сделайте тип аргумента const ClassName& конструктора копирования. Это предотвращает случайное изменение скопированного объекта конструктором копирования. Он также позволяет копировать из const объектов.

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

Конструкторы копирования, созданные компилятором, например определяемые пользователем конструкторы копирования, имеют один аргумент типа "ссылка на имя класса". Исключение заключается в том, что все базовые классы и классы-члены имеют конструкторы копирования, объявленные как принимающие один аргумент типа const class-name&>. В таком случае аргумент конструктора копирования, созданного компилятором, также constявляется .

Если тип аргумента конструктору копирования не constявляется, инициализация путем копирования const объекта создает ошибку. Обратный аргумент не имеет значения true: если аргумент constимеет значение, можно инициализировать, скопировав объект, который не constявляется.

Операторы назначения, созданные компилятором, соответствуют тому же шаблону const. Они принимают один аргумент типа ClassName& , если операторы назначения во всех базовых и классах членов не принимают аргументы типа const ClassName&. В этом случае созданный оператор назначения для класса принимает const аргумент.

Примечание.

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

Последствия аналогичны конструктору копирования. Если тип аргумента не constявляется, назначение из const объекта создает ошибку. Обратный аргумент не имеет значения: если const значение присваивается значению, которое не constявляется, назначение завершается успешно.

Дополнительные сведения о перегруженных операторах назначения см. в разделе "Назначение".