Оператор присваивания (C++)
В C языке программирования оператор присваивания ++ =
, — оператор, используемый для присваивания . Как и большинство других операторов в C++, его можно перегрузить .
Оператор копирования копирования , часто называемый просто «оператором присваивания», представляет собой особый случай оператора присваивания, когда источник (правая часть) и пункт назначения (левая часть) относятся к одному и тому же типу класса . Это одна из специальных функций-членов , что означает, что ее версия по умолчанию генерируется компилятором автоматически, если программист ее не объявляет . Версия по умолчанию выполняет копирование по каждому элементу, при этом каждый член копируется своим собственным оператором присваивания копии (который также может быть объявлен программистом или создан компилятором).
Оператор копирования копирования отличается от конструктора копирования тем, что он должен очищать элементы данных цели назначения (и правильно обрабатывать самоназначение), тогда как конструктор копирования присваивает значения неинициализированным элементам данных. [ 1 ] Например:
My_Array first; // initialization by default constructor
My_Array second(first); // initialization by copy constructor
My_Array third = first; // Also initialization by copy constructor
second = third; // assignment by copy assignment operator
Возвращаемое значение перегруженного оператора присваивания
[ редактировать ]Язык позволяет перегруженному оператору присваивания иметь произвольный тип возвращаемого значения (включая void
). Однако оператор обычно определяется для возврата ссылки на правопреемника. Это согласуется с поведением оператора присваивания для встроенных типов ( возвращает присвоенное значение ) и позволяет использовать вызов оператора в качестве выражения, например, в операторах управления или в цепном присваивании . Кроме того, стандартная библиотека C++ требует такого поведения для некоторых типов, предоставляемых пользователем. [ 2 ]
Перегрузка оператора присваивания копии
[ редактировать ]Когда глубокие копии необходимо сделать безопасность исключений объектов, следует учитывать . Один из способов добиться этого, когда освобождение ресурсов никогда не завершается неудачей, заключается в следующем:
- Приобретайте новые ресурсы
- Освободите старые ресурсы
- Назначьте дескрипторы новых ресурсов объекту.
class My_Array{
int* array;
int count;
public:
My_Array& operator=(const My_Array& other)
{
if (this != &other) { // protect against invalid self-assignment
// 1: allocate new memory and copy the elements
int* new_array = new int[other.count];
std::copy(other.array, other.array + other.count, new_array);
// 2: deallocate old memory
delete[] array;
// 3: assign the new memory to the object
array = new_array;
count = other.count;
}
// by convention, always return *this
return *this;
}
// ...
};
Однако, если для всех подобъектов-членов доступна безотказная ( no-throw ) функция обмена и класс предоставляет копирования конструктор и деструктор (что он должен делать в соответствии с правилом трех ), наиболее простой способ реализовать копирование задание следующее: [ 3 ]
public:
void swap(My_Array& other) // the swap member function (should never fail!)
{
// swap all the members (and base subobject, if applicable) with other
using std::swap; // because of ADL the compiler will use
// custom swap for members if it exists
// falling back to std::swap
swap(array, other.array);
swap(count, other.count);
}
My_Array& operator = (My_Array other) // note: argument passed by value!
{
// swap this with other
swap(other);
// by convention, always return *this
return *this;
// other is destroyed, releasing the memory
}
Распределение между разными классами
[ редактировать ]C++ поддерживает присваивание между различными классами как через неявный конструктор копирования , так и через оператор присваивания, если целевой класс экземпляра является предком исходного класса экземпляра:
class Ancestor {
public:
int a;
};
class Descendant : public Ancestor {
public:
int b;
};
int main()
{
Descendant d;
Ancestor a(d);
Ancestor b(d);
a = d;
}
Копирование объектов-предков в объекты-потомки, в результате которого поля потомков могут остаться неинициализированными, не допускается.
См. также
[ редактировать ]- Перегрузка оператора
- Переместить оператор присваивания
- Правило трех (программирование на C++)
- Операторы в C и C++
Ссылки
[ редактировать ]- ^ Страуструп, Бьярне (2000). Язык программирования C ++ (3-е изд.). Аддисон-Уэсли. п. 244. ИСБН 978-0-201-70073-2 .
- ^ Рабочий проект стандарта языка программирования C++, раздел 17.6.3.1, таблица 23; http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf
- ^ Саттер, Х .; Александреску, А. (октябрь 2004 г.), Стандарты кодирования C++ , Аддисон-Уэсли , ISBN 0-321-11358-6
Внешние ссылки
[ редактировать ]- Анатомия оператора присваивания Ричарда Гиллама