我是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;
}
当我跑它崩溃。如果我删除析构函数,它的工作原理。为什么会这样?
答案 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。