Сокращение дублирования кода между оператором = и конструктором копирования
У меня есть класс, который требует конструктор копирования не по умолчанию и оператор присваивания (он содержит списки указателей). Есть ли какой-либо общий способ уменьшить дублирование кода между конструктором копирования и оператором присваивания?
4 ответа
Не существует "общего способа" для написания пользовательских конструкторов копирования и операторов присваивания, который работает во всех случаях. Но есть идиома, которая называется "копировать и обменять":
class myclass
{
...
public:
myclass(myclass const&);
void swap(myclass & with);
myclass& operator=(myclass copy) {
this->swap(copy);
return *this;
}
...
};
Это полезно во многих (но не во всех) ситуациях. Иногда вы можете сделать лучше. Вектор или строка могут иметь лучшее назначение, которое повторно использует выделенное хранилище, если оно достаточно велико.
Вынести общий код в приватную функцию-член. Простой (довольно надуманный) пример:
#include <iostream>
class Test
{
public:
Test(const char* n)
{
name = new char[20];
strcpy(name, n);
}
~Test()
{
delete[] name;
}
// Copy constructor
Test(const Test& t)
{
std::cout << "In copy constructor.\n";
MakeDeepCopy(t);
}
// Assignment operator
const Test& operator=(const Test& t)
{
std::cout << "In assignment operator.\n";
MakeDeepCopy(t);
}
const char* get_name() const { return name; }
private:
// Common function where the actual copying happens.
void MakeDeepCopy(const Test& t)
{
strcpy(name, t.name);
}
private:
char* name;
};
int
main()
{
Test t("vijay");
Test t2(t); // Calls copy constructor.
Test t3("");
t3 = t2; // Calls the assignment operator.
std::cout << t.get_name() << ", " << t2.get_name() << ", " << t3.get_name() << '\n';
return 0;
}
My &My::operator = (My temp) // thanks, sellibitze
{
swap (*this, temp);
return *this;
}
и реализовать специализированный std::swap<> (My &, My &)
,
Как уже указывалось многими авторами, использование оператора = создать новый объект с помощью конструктора копирования, а затем использование свопа - это обычная техника, используемая для того, чтобы не дублировать код в operator=.
Тем не менее, я хочу указать на некоторые плюсы и минусы этой техники, чтобы помочь вам решить, подходит ли она.
Pro - исключение безопасности
Если у вашего объекта есть требования к ресурсам, которые могут вызвать выброс, и предполагая, что обмен не сработает, этот метод обеспечивает надежную гарантию безопасности исключений (либо объект, который назначен, принял значение другого объекта, либо он не изменился).
Con - ресурсный след
Проблема с этой техникой заключается в том, что она требует создания нового объекта до выпуска старого. Если ваш объект требует много ресурсов, это может быть проблемой.