为什么析构函数在被调用时会产生错误?

时间:2015-11-03 12:49:34

标签: c++ class pointers memory destructor

我创建了一个Calendar类,其中一切似乎都运行正常但是在程序结束之前,当调用析构函数时它会导致调试断言失败!

这是班级:

    //constructor
Calendar::Calendar(const int *pday, const int *pmonth, const int *pyear){
    day = new int(sizeof(pday));
    month = new int(sizeof(pmonth));
    year = new int(sizeof(pyear));

    day = pday;
    month = pmonth;
    year = pyear;
}

//copy constructor
Calendar::Calendar(const Calendar &rhs){
    day = new int(sizeof(rhs.day));
    month = new int(sizeof(rhs.month));
    year = new int(sizeof(rhs.year));

    day = rhs.day;
    month = rhs.month;
    year = rhs.year;
}

//operator '=' overload
Calendar& Calendar::operator=(const Calendar &rhs){
    delete[] day;
    delete[] month;
    delete[] year;

    day = new int(sizeof(rhs.day));
    month = new int(sizeof(rhs.month));
    year = new int(sizeof(rhs.year));

    day = rhs.day;
    month = rhs.month;
    year = rhs.year;

    return *this;
}

//deconstructor
Calendar::~Calendar(){
    delete[] day;
    delete[] month;
    delete[] year;
}

可能是什么问题?我不是为类的变量创建内存吗?

3 个答案:

答案 0 :(得分:4)

使用new创建指针时,请使用delete将其删除。当您使用new[]创建指针时,请使用delete[]将其删除。混合它们是不确定的行为,这就是你正在做的事情。您可以使用new创建指针,但可以使用delete[]

将其删除

我相信你的意思是创建像

这样的指针
day = new int;
month = new int;
year = new int;

你为什么在这里使用指针?使用指针似乎不是这里的方法。存储日,月和年的简单Calendar类可以实现为

Calendar
{
private:
    int day_;
    int month_;
    int year_;
public:
    Calendar(int day = 0, int month = 0, int year = 0) : day_(day), month_(month), year_(year) {}
};

现在默认的复制构造函数,赋值运算符和析构函数对你有用,并且没有指针可以处理。

答案 1 :(得分:1)

不,您没有正确构建数据。

day = pday;
month = pmonth;
year = pyear;

是一个指针赋值,从参数复制地址,而不是它们的值。

正确的方法是(假设我们要复制1个元素):

*day = *pday;
*month = *pmonth;
*year = *pyear;

您还将数组删除delete[]与单个元素new混合(不包含[])。这是未定义的行为。

另外,day = new int(sizeof(pday));创建了一个int,其初始化值为指针的大小。这看起来很奇怪。

答案 2 :(得分:1)

让我们看一下你的拷贝构造函数:

Calendar::Calendar(const Calendar &rhs){
    day = new int(sizeof(rhs.day));
    month = new int(sizeof(rhs.month));
    year = new int(sizeof(rhs.year));

    day = rhs.day;
    month = rhs.month;
    year = rhs.year;
}

首先,您分配内存并将其分配给您的成员。然后用来自rhs对象的指针覆盖此对象中的指针,导致两个对象都指向同一个内存。当其中一个对象被破坏时,其他对象将有杂散指针,试图删除它们将导致未定义的行为

一种解决方案是使用解除引用来复制值,例如

*day = *rhs.day;

但我真的认为这里根本不需要指针,这意味着你不需要分配内存,你不需要担心复制,你不必担心内存泄漏的杂散指针。实际上,如果你没有指针,你甚至不需要复制构造函数,赋值运算符或析构函数。我建议你阅读the rule of zero