C++ 调用析构函数时出错

C++ 调用析构函数时出错,c++,C++,嗨,我在学习运算符重载。。我注意到程序在调用析构函数时崩溃了。。感谢您的帮助。 谢谢 #包括 使用名称空间std; 类重载 { 私人: INTA,*b; 公众: 重载():a(0){cout b)+*(rhs.b); cout您应该实现,并且。默认构造函数使b处于未初始化状态。换句话说,您的代码没有在有效状态下构造对象。b当析构函数调用delete[]b时,它可能是任何东西。这会导致错误--您还期望什么 与此相关的一个问题是,默认构造的复制构造函数和复制赋值运算符只会复制b。因此,如果从中复制的

嗨,我在学习运算符重载。。我注意到程序在调用析构函数时崩溃了。。感谢您的帮助。 谢谢

#包括
使用名称空间std;
类重载
{
私人:
INTA,*b;
公众:
重载():a(0){cout b)+*(rhs.b);

cout您应该实现,并且。

默认构造函数使
b
处于未初始化状态。换句话说,您的代码没有在有效状态下构造对象。
b
当析构函数调用
delete[]b
时,它可能是任何东西。这会导致错误--您还期望什么

与此相关的一个问题是,默认构造的复制构造函数和复制赋值运算符只会复制
b
。因此,如果从中复制的对象被销毁,则复制到的对象将留下一个悬空指针,这将在其销毁时导致错误


主要教训是:如果你不知道自己在做什么(你也不知道),不要使用原始指针。而是使用
std::vector
std::unique_ptr
或标准提供的其他方法来处理这些事情。

有两个严重的错误会导致你的错误:

1.缓冲区溢出:

第一个致命错误是
setb()
中的缓冲区溢出:
b
指向
a
元素数组,因此设置b[a]时可能会损坏内存:

for (int i = 0; i < a; i++)  // strictly < a, not <=a !!
但是,由于您既没有定义复制构造函数,也没有定义赋值运算符,因此使用了默认的构造函数。它们将创建对象的成员副本,即指针只是按原样复制。结果是
Z.b
将包含指针
temp.b
的副本,但
temp.b
已在o末尾被删除f运算符+()!因此Z将引用一个悬空指针,造成很大的伤害,特别是当离开main()时,Z的析构函数将再次尝试删除它

创建一个复制构造函数和一个赋值运算符,正确地分配一个新的
b
指针。这将解决第二个问题

请不要像增加
(this->b++
)那样增加操作数的指针:它会永久更改b指针,并且当操作数超出范围时,delete将无法识别它

顺便说一句,即使这不是问题的直接原因,也可以通过添加两个操作数的大小来初始化
temp
size
a
,但只能为第一个操作数的大小分配
b

3.其他备注:

默认构造函数不会明确地将
b
初始化为
nullptr
。这样做是安全的做法,但这并不是问题的直接原因

在operator+()中,在不访问其内部的情况下初始化temp将是一种良好的做法:
重载temp(a);
将更易于维护,更不容易出错

我不知道这是否是您的意图,但只添加了由b指向的数组的第一个值:
*temp.b=*(this->b)+*(rhs.b);
就像在
main()
中使用的最大大小为1时一样,这不是问题。但是为了将来,最好使用循环来复制所有元素

最后一句话:你有没有想过你的类的用户可能会做一些奇怪的事情,比如:
重载E,G(0),H(1);E=H+G;
你的操作符+不会尝试访问空指针吗

for (int i = 0; i < a; i++)  // strictly < a, not <=a !!
Overload temp;  // you create a logcal temporary object
...
temp.b = new int[temp.a];  // you allocate the array
...
return b;   // you return a COPY of the temp object 
}           // here the local temp object gets destroyed