未分配正在释放的指针 - 析构函数

Pointer being freed was not allocated - destructor

慢慢学习 copy/move 构造函数,规则 5 等。加上对 pointers/reference 的用法不太了解,我无法理解为什么我的析构函数会抛出以下错误。我知道是只有析构函数和析构函数引起的,并且在拷贝构造函数之后。

untitled(19615,0x104a60580) malloc: *** error for object 0x600000b74000: pointer being freed was not allocated

untitled(19615,0x104a60580) malloc: *** set a breakpoint in malloc_error_break to debug

代码:

#include <string>

using namespace std;
typedef int size_type;

class user{
public:
    user():
    rank(1),
    name("default"){
    }
private:
    int rank;
    string name;
};

class account{
public:
    account(size_type max_size):
    owners(new user[max_size]),
    max_size(max_size){
        cout<<"normal constructor"<<endl;
    }
    account(account& other):
    owners(other.owners),
    max_size(sizeof(owners)){
        cout<<"copy constructor called"<<endl;
    }
    account(account&& other):
    owners(other.owners),
    max_size(sizeof(owners)){
        cout<<"move constructor called"<<endl;
    }
    ~account(){
        if(owners!= NULL) {
            delete[] owners;
            owners= 0;
        }
        cout<<"destructor called"<<endl;
    }

private:
    user* owners;
    size_type max_size;
};

int main(){
    account f(3);
    account n(f);
}

I cannot understand why my destructor throws the error below. I know that it's caused by destructor and destructor only

account f(3);

这个对象的构造函数分配了一个数组。

account n(f);

您编写的复制构造函数复制指向动态数组的指针。

n先被销毁。它的析构函数删除数组。 f 之后被销毁。它的析构函数也删除了相同的数组,并且程序的行为是未定义的,这导致了您观察到的输出。

为了防止分配被多次删除,您必须强制执行 class 不变量(适用于所有成员函数的 post 条件)任何 non-null owners 值在 class 的所有实例中必须是唯一的。要在复制构造函数(以及移动构造函数和复制和移动赋值运算符)中保持不变,您不能像现在那样复制指针。我建议学习RAII成语。

更好的解决方案:不要使用拥有裸指针。使用 std::vector<user> 并且根本没有用户定义的特殊成员函数。

P.S。复制构造函数应该接受对 const.

的引用

还有:

if(owners!= NULL) {
    delete[] owners;
    owners= 0;
}

检查是多余的,因为删除 null 是安全的。该赋值是多余的,因为该对象即将被销毁并且之后无论如何都无法访问该成员。