Операция присваивания в С++

Из Википедии, бесплатной энциклопедии

Операция присваивания в языке программирования C++ обозначается знаком '='. Как и другие операторы в C++, она может быть перегружена.

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

Операция присваивания копированием отличается от конструктора копирования тем, что должна очищать члены-данные цели присваивания (и правильно обрабатывать самоприсваивание), тогда как конструктор копирования присваивает значения неинициализированным членам-данным.[1] Например:

My_Array first;           // инициализация конструктором по умолчанию My_Array second = first;  // инициализация конструктором копирования second = first;           // присваивание операцией присваивания копированием 

В качестве особого случая следует отметить следующий вариант инициализации конструктором копирования:

My_Array second = My_Array(); 

В этом случае компилятор (например VC2013) сразу же без всяких опций оптимизации выполняет оптимизацию возвращаемого значения (RVO, return value optimization) и конструктор копирования не вызывается.

Перегрузка операции присваивания копированием

[править | править код]

Когда нужно сделать глубокие копии объектов необходимо также принять во внимание и обработку исключений. Одним из способов избежать ошибки перемещения ресурсов является следующий:

  1. Получаем новые ресурсы
  2. Освобождаем старые ресурсы
  3. Присваиваем объекту значения нового ресурса
class My_Array  {      int * array;     int count;  public:      My_Array & operator = (const My_Array & other)     {         if (this != &other) // защита от неправильного самоприсваивания         {             // 1: выделяем "новую" память и копируем элементы             int * new_array = new int[other.count];             std::copy(other.array, other.array + other.count, new_array);              // 2: освобождаем "старую" память             delete [] array;              // 3: присваиваем значения в "новой" памяти объекту             array = new_array;             count = other.count;         }         // по соглашению всегда возвращаем *this         return *this;     }      ...  }; 

Тем не менее, если успешный метод обмена доступен для всех членов и класс реализует конструктор копирования и деструктор (согласно Правилу трёх), самым коротким путём реализации присваивания копированием будет следующий способ[2]:

public:      void swap(My_Array & other) // обмен члена-функции (неудачи быть не должно!)     {         // обмен всех членов (и базовых субобъектов, если возможно) с other         std::swap(array, other.array);         std::swap(count, other.count);     }      My_Array & operator = (My_Array other) // Примечание: аргумент передается по значению!     {         // обмен this с other         swap(other);          // по соглашению всегда возвращаем *this         return *this;          // other уничтожается, освобождая память     } 

Причина, по которой операция = возвращает My_Array& вместо void, проста. Он разрешён для объединения присваиваний, как например:

array_1 = array_2 = array_3; // значение array_3 присваивается array_2                               // затем значение array_2 присваивается array_1 
  1. Bjarne Stroustrup. The C++ Programming Language (неопр.). — 3. — Addison-Wesley, 2000. — С. 244. — ISBN 978-0201700732.
  2. Sutter, H.; Alexandrescu, A. (October 2004), C++ Coding Standards, Addison-Wesley, ISBN 0-321-11358-6{{citation}}: Википедия:Обслуживание CS1 (дата и год) (ссылка)