为什么析构函数在被调用时会产生错误?
Why does destructor create a bug when it's being called?
我创建了一个日历 class,其中一切似乎都运行良好,但就在程序结束之前,当调用析构函数时,它会导致调试断言失败!
这是class:
//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;
}
可能是什么问题?我不是在为 class 的变量创建内存吗?
当您使用 new
创建指针时,您会使用 delete
删除它。使用 new[]
创建指针时,使用 delete[]
删除它。混合它们是未定义的行为,这就是你正在做的。您使用 new
创建指针,但使用 delete[]
删除它
我相信你打算创建像
这样的指针
day = new int;
month = new int;
year = new int;
你为什么在这里使用指针?在这里使用指针似乎不是办法。一个简单的 Calendar
class 存储日、月、年可以实现为
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) {}
};
现在默认的复制构造函数、赋值运算符和析构函数将为您工作,没有指针需要处理。
不,您没有正确构建数据。
day = pday;
month = pmonth;
year = pyear;
是一个指针赋值,从参数中复制地址,而不是它们的值。
正确的做法是(假设我们要复制1个元素):
*day = *pday;
*month = *pmonth;
*year = *pyear;
您还混合了数组删除 delete[]
和单个元素 new
(没有 []
)。那是未定义的行为。
还有一件事,day = new int(sizeof(pday));
创建了一个 int
初始化为一个指针大小的值。这似乎很奇怪。
让我们看看你的拷贝构造函数:
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.
的内容
我创建了一个日历 class,其中一切似乎都运行良好,但就在程序结束之前,当调用析构函数时,它会导致调试断言失败!
这是class:
//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;
}
可能是什么问题?我不是在为 class 的变量创建内存吗?
当您使用 new
创建指针时,您会使用 delete
删除它。使用 new[]
创建指针时,使用 delete[]
删除它。混合它们是未定义的行为,这就是你正在做的。您使用 new
创建指针,但使用 delete[]
我相信你打算创建像
这样的指针day = new int;
month = new int;
year = new int;
你为什么在这里使用指针?在这里使用指针似乎不是办法。一个简单的 Calendar
class 存储日、月、年可以实现为
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) {}
};
现在默认的复制构造函数、赋值运算符和析构函数将为您工作,没有指针需要处理。
不,您没有正确构建数据。
day = pday;
month = pmonth;
year = pyear;
是一个指针赋值,从参数中复制地址,而不是它们的值。
正确的做法是(假设我们要复制1个元素):
*day = *pday;
*month = *pmonth;
*year = *pyear;
您还混合了数组删除 delete[]
和单个元素 new
(没有 []
)。那是未定义的行为。
还有一件事,day = new int(sizeof(pday));
创建了一个 int
初始化为一个指针大小的值。这似乎很奇怪。
让我们看看你的拷贝构造函数:
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.
的内容