[使用析构函数并复制构造函数的C ++ assingment运算符

问题描述 投票:0回答:1

我正在研究具有多个动态字段的类,并且我正在寻找编码赋值运算符的快速方法。

因此,我有一些基本类Cla,它存储整数的动态数组(arr)和该数组的大小(n)。

我已经对此进行了编码:

Cla::Cla(int* arr, int n) : n(n)
{
    this->arr = new int[n];

    //allocation error handling

    while (--n >= 0)
        this->arr[n] = arr[n];
}


Cla::~Cla()
{
    delete[] arr;
}

Cla::Cla(const Cla& copy) : Cla(copy.arr, copy.n){}

Cla& Cla::operator= (const Cla& asg)
{
    this->~Cla();
    *this = asg;
    return *this;
}

[operator=除外,所有正常工作。我的想法是,我将销毁我的对象,然后使用复制构造函数再次创建它(为简化示例,我不考虑两个对象具有相同大小且无需释放和新分配)。它可以编译,但是执行时却给了我一些讨厌的错误。

您能给我一些有关如何更正此代码的建议吗?这样工作是否有可能?(我知道如何编写一个赋值运算符,我只是问是否可以使用析构函数和复制构造函数来实现。我在互联网上找不到类似的东西。)

c++ operator-overloading destructor
1个回答
0
投票

您的operator=具有未定义的行为。首先,您不能在未使用placement-new分配的对象上手动调用析构函数。其次,一旦对象被销毁,将无法再使用它,这意味着一旦placement-new被调用,*this = asg将访问无效内存,因为this->~Cla()不再指向有效对象。第三,您的this正在运行一个无限递归循环,一遍又一遍地调用自己,直到调用堆栈崩溃为止(如果幸运的话)。

由于要使用副本构造函数,因此最好使用operator=来更好地服务operator=。构造一个本地对象以使用您的副本构造函数,然后用copy-swap idiom交换该对象的内容,例如:

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;
}

话虽如此,您的复制构造函数是delegating到转换构造函数的事实,这意味着您使用的是C ++ 11或更高版本,在这种情况下,您还应该在类中实现移动语义,而不仅仅是复制语义,例如:

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;
}

通过按值传递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=参数时,编译器将选择适当的构造函数。

© www.soinside.com 2019 - 2024. All rights reserved.