对象的析构函数导致崩溃

Destructor of object cause crashing

本文关键字:崩溃 析构函数 对象      更新时间:2023-10-16

我是个c++新手。反正我也有个解决不了的问题。我写了一个代码来更好地理解类和重载操作符:

#include <iostream>
#include <stdlib.h>
#include <stdarg.h>
using namespace std;
class vectmy {
public:
    int size;   
int *a;
vectmy(int n,int val);
~vectmy (){delete[] a;   //IF I DELETE THIS PROGRAM WORKS
}
vectmy & operator = (const vectmy &);
};
 vectmy::vectmy(int n,int val){
    size=n;
    a = new int[ n+1 ];
    for (int i=0;i<n;++i){
    *(a+i)=val;
    }
 }

   vectmy& vectmy::operator= (const vectmy& param)
  {
   for (int i=0;i<3;++i)    a[i]=param.a[i];
    return *this;
   }

 vectmy operator+( vectmy left, vectmy right)
  {
  vectmy result = left;
  for (int i=0;i<3;++i) result.a[i]=result.a[i]+right.a[i];
  return result;
   }

int main() {
int b1[3]={1,2,4};
vectmy d(3,2),b(3,4),c(3,0);
c=(b+d);
for (int j=0; j<3; ++j)cout<<c.a[j]<<' '<<endl; 
return 0;
}

当我运行它崩溃。如果我移除析构函数,它就会工作。为什么会这样?

当我运行它崩溃。如果我移除析构函数,它就会工作。为什么会这样?

您的operator +创建了left副本:

vectmy result = left;

由于没有显式地定义复制构造函数,编译器将隐式地生成一个执行成员复制的构造函数。

a数据成员的沉闷副本意味着a指针最终将指向两个不同的vectmy实例(resultleft)的相同的位置,它们都将在销毁时delete[]它。

这样的双重删除给你的程序未定义的行为,在你的情况下表现为崩溃。

这就是三规则: 的意义所在每当您有一个用户定义的复制构造函数、赋值操作符或析构函数时,您可能应该定义所有

原因是您通常定义其中一个函数,因为您正在管理某些资源(在您的情况下是内存),并且您通常希望在复制,解构或分配管理资源的对象时执行适当的操作。

在这个特殊的例子中,缺少一个合适的复制构造函数。你可以这样定义它:

vectmy::vectmy(vectmy const& v)
{
    size=v.size;
    a = new int[size];
    *this = v;
}

此外,我建议您尽可能避免通过原始指针、newdelete(或它们的数组对应物)进行手动内存管理,并考虑使用std::vector

更新:

还要注意,您的operator +通过值接受其参数,这意味着每个参数将被复制(即,将调用复制构造函数)。

由于这里不需要复制,您可能希望通过引用(到const)来获取参数:

vectmy operator + ( vectmy const& left, vectmy const& right)
//                         ^^^^^^              ^^^^^^

在你的operator+

vectmy result = left;

这将调用默认构造函数复制构造函数,您没有它们。因此将使用编译器变体,这不会为a成员分配内存。对于自动生成的复制构造函数,指针将被简单地复制,使两个对象使用同一个指针。当其中一个指针删除时,另一个指针失效。

你应该读读"三原则"