对象的析构函数导致崩溃

时间:2013-04-20 11:25:25

标签: c++ class destructor

我是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;
}

当我跑它崩溃。如果我删除析构函数,它的工作原理。为什么会这样?

2 个答案:

答案 0 :(得分:4)

  

当我跑它崩溃。如果我删除析构函数,它的工作原理。为什么会这样?

您的operator +在此创建了left副本

vectmy result = left;

由于您尚未明确定义复制构造函数,因此编译器将生成一个隐式执行成员复制的复制构造函数。

a数据成员的枯燥副本意味着a指针最终将指向<{1}}的两个不同实例的相同位置({ {1}}和vectmy),这两个在销毁后result

这种双重删除会为您的程序提供未定义的行为,在您的情况下会将其显示为崩溃。

这是Rule of Three的每一个点,每次你有一个用户定义的拷贝构造函数,赋值运算符或析构函数时,你应该定义它们的全部

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

在这种特殊情况下,缺少正确的拷贝构造函数。这就是你如何定义它:

left

此外,我建议您尽可能避免通过原始指针delete[]vectmy::vectmy(vectmy const& v) { size=v.size; a = new int[size]; *this = v; } (或其数组对应物)进行手动内存管理,并考虑使用std::vector

<强>更新

另请注意,您的new正在接受其参数按值,这意味着每个参数都将被复制(即,复制构造函数将是调用)。

由于此处不需要复制,您可能希望通过引用(delete)来获取参数:

operator +

答案 1 :(得分:1)

operator+你做

vectmy result = left;

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

您应该阅读the rule of three