Ваш operator=
имеет неопределенное поведение. Во-первых, вы не можете вручную вызвать деструктор для объекта, который не был выделен с placement-new
. Во-вторых, как только объект уничтожен, он больше не может использоваться, что означает, что *this = asg
обращается к недопустимой памяти после вызова this->~Cla()
, так как this
больше не указывает на действительный объект. В-третьих, ваш operator=
выполняет бесконечную рекурсию l oop, вызывая себя снова и снова, пока стек вызовов не взорвется (если вам повезет).
Поскольку вы хотите использовать свой конструктор копирования, ваш operator=
лучше использовать вместо copy-swap idiom . Создайте локальный объект, чтобы использовать ваш конструктор копирования, а затем поменяйте содержимое этого объекта на this
, чтобы this
стал владельцем скопированных данных, а локальный объект освобождает старые данные, когда он выходит из области видимости, Например:
Cla& Cla::operator= (const Cla& asg)
{
if (&asg != this)
{
Cla temp(asg);
std::swap(arr, temp.arr);
std::swap(n, temp.n);
}
return *this;
}
В качестве альтернативы:
void Cla::swap(Cla &other)
{
std::swap(arr, other.arr);
std::swap(n, other.n);
}
Cla& Cla::operator= (const Cla& asg)
{
if (&asg != this) {
Cla(asg).swap(*this);
}
return *this;
}
При этом факт, что ваш конструктор копирования делегирует вашему конструктору преобразования, означает, что вы используете C ++ 11 или более поздней версии, и в этом случае вы должны также реализовать семантику перемещения в своем классе, а не просто копировать семантику, например:
Cla::Cla() : arr(nullptr), n(0)
{
}
Cla::Cla(int* arr, int n) : arr(new int[n]), n(n)
{
while (--n >= 0)
this->arr[n] = arr[n];
}
Cla::Cla(Cla &&c) : arr(nullptr), n(0)
{
c.swap(*this);
}
Cla::Cla(const Cla& c) : Cla(c.arr, c.n)
{
}
Cla::~Cla()
{
delete[] arr;
}
void Cla::swap(Cla &other)
{
std::swap(arr, other.arr);
std::swap(n, other.n);
}
Cla& Cla::operator= (Cla asg)
{
asg.swap(*this);
return *this;
}
Передав параметр asg
по значению, operator=
может решить использовать ли семантику копирования или перемещать семантику на сайте вызова в зависимости от того, передается ли ему значение lvalue или rvalue. Компилятор выберет соответствующий конструктор для создания параметра asg
, а затем this
может стать владельцем полученных данных.