我无法理解这种行为。我有一个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){}
};
A
的默认构造函数不会初始化成员s
(指针(:
A()
{}
因此,当使用此构造函数构造元素时,当析构函数删除未初始化的元素时,会发生崩溃:
~A()
{
delete []s;
}
类B
使用A
的默认构造函数,因此会触发此问题。通过正确初始化默认构造函数中的所有成员来避免它:
A() : ch(), s(0)
{ }
要解决您的问题,您所需要做的就是替换:
char *s;
带有
std::string s;
只需通过char *
摆脱手动内存管理,这正是C++为您提供std::string
的原因。
可能是什么问题
您的默认构造函数不接受任何参数,不进行动态分配
如果您通过此构造函数创建类对象,那么您的析构函数最终会delete
返回一个未分配给new
的指针,从而导致Undefined Behavior。
在析构函数中,您delete[] s;
,但在默认构造函数中,您没有new[]
ed s。事实上,您甚至还没有初始化s
。
实例化派生类时会调用基类的默认构造函数,因为您没有初始化基类(: A(...)
(。因此,你不知道你要删除什么,甚至不知道你明天早餐要吃什么,因为这是未定义的行为。
为了保持一致,new[]
在默认构造函数中。为了避免头痛,我建议使用类似std::string
的内容,而不是字符指针。