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
sizea
,但只能为第一个操作数的大小分配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