2

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

当我运行它崩溃。如果我删除它的析构函数。为什么会发生?

4

2 回答 2

4

当我运行它崩溃。如果我删除它的析构函数。为什么会发生?

您在此处operator +创建副本left

vectmy result = left;

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

数据成员的无意义副本a意味着a指针最终将指向(和)的两个不同实例的同一位置,这两个实例将在销毁时指向。vectmyresultleftdelete[]

这种双重删除会给您的程序带来未定义的行为,在您的情况下表现为崩溃。

这就是三法则的要点:每次您有一个用户定义的复制构造函数、赋值运算符或析构函数时,您可能应该定义所有这些

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

在这种特殊情况下,缺少正确的复制构造函数。你可以这样定义它:

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

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

更新:

另请注意,您通过 valueoperator +接受其参数,这意味着将复制每个参数(即,将调用复制构造函数)。

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

vectmy operator + ( vectmy const& left, vectmy const& right)
//                         ^^^^^^              ^^^^^^
于 2013-04-20T11:30:54.667 回答
1

operator+你做的

vectmy result = left;

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

您应该阅读有关三的规则

于 2013-04-20T11:30:06.123 回答