1

我无法理解这种行为。我有一个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){}
};
4

3 回答 3

3

要解决您的问题,您需要做的就是更换:

char *s;

std::string s;

只需通过 摆脱手动内存管理char *,这正是 C++ 为您提供的原因std::string

可能是什么问题?

您的不带任何参数的默认构造函数不会进行动态分配。
如果您通过此构造函数创建了类对象,则您的析构函数最终会delete生成一个未分配的指针,new从而导致未定义的行为。

于 2013-01-04T08:05:40.507 回答
3

在析构函数中, you delete[] s;,但在默认构造函数中,你没有new[]ed 。事实上,你甚至还没有初始化s.

基类的默认构造函数在您实例化派生类时被调用,因为否则您尚未初始化基类 ( : A(...))。因此,您不知道要删除什么,甚至不知道明天早餐要吃什么,因为这是未定义的行为。

为了保持一致,new[]s 在默认构造函数中。为了避免头痛,我建议使用类似的东西std::string而不是字符指针。

于 2013-01-04T08:06:28.577 回答
3

您的默认构造函数A不会初始化成员s(指针):

A()
{}

因此,当使用此构造函数构造元素时,当析构函数删除未初始化的元素时会崩溃:

~A()
{
  delete []s;
}

B使用默认构造函数A,因此会触发此问题。通过在默认构造函数中正确初始化所有成员来避免它:

A() : ch(), s(0)
{ }
于 2013-01-04T08:08:03.970 回答