我无法理解这种行为。我有一个A级,
class A
{
public:
int ch;
char *s;
A()
{}
A(char *st):ch(0)
{
s = new char[10];
strcpy(s,st);
}
A(const A& rhs):ch(rhs.ch)
{
s = new char[strlen(rhs.s)+1];
strcpy(s,rhs.s);
}
const A& operator=(const A& rhs)
{
char *temp = new char[strlen(rhs.s)+1];
strcpy(temp,rhs.s);
delete[] s;
s=temp;
ch = rhs.ch;
return *this;
}
~A()
{
delete []s;
}
};
直到这一点,一切都按预期进行,我能够测试我的复制构造函数和赋值运算符,并且它们正常工作。
现在我创建了一个子类B,我收到了堆损坏错误。我无法理解,这是与A类析构函数有关的问题。 ? 以下是我的B级,
class B:public A
{
public:
int a;
B():a(0){}
};
答案 0 :(得分:3)
要解决您的问题,您只需要替换:
char *s;
带
std::string s;
通过char *
摆脱手动内存管理,这正是C ++为您提供std::string
的原因。
可能是什么问题?
不带任何参数的默认构造函数不进行动态分配
如果您通过此构造函数创建了类对象,则析构函数最终delete
指向未使用new
分配的指针,从而导致未定义的行为。
答案 1 :(得分:3)
在析构函数中,您delete[] s;
,但在默认构造函数中,您还没有new[]
编辑。事实上,你甚至没有初始化s
。
实例化派生类时会调用基类的默认构造函数,因为您尚未初始化基类(: A(...)
)。因此,您不知道自己要删除的内容,甚至是明天的早餐,因为它未定义的行为。
为了保持一致,new[]
在默认构造函数中。为了避免头痛,我建议使用std::string
而不是字符指针。
答案 2 :(得分:3)
A
的默认构造函数未初始化成员s
(指针):
A()
{}
因此,当使用此构造函数构造元素时,析构函数删除未初始化元素时会出现崩溃:
~A()
{
delete []s;
}
类B
使用A
的默认构造函数,因此会触发此问题。通过正确初始化默认构造函数中的所有成员来避免它:
A() : ch(), s(0)
{ }