3

我正在阅读 C++ Primer Plus 一书的第 13 章。它有一个示例处理使用继承与动态内存分配、复制构造函数和重载 = 运算符。

被调用的基类有一个在构造函数baseDMA中使用的指向字符的私有指针。new

class baseDMA
{
private:
   char * label;

...
};

baseDMA::baseDMA(const char * l)
{
    label = new char[std::strlen(l) + 1];
    std::strcpy(label, l);
    ...
}

现在,当重载=运算符时,我们删除了,label pointer因为我们将把它分配给一个新值,它将指向一个新位置。如果我们不删除它,那么以后我们将无法这样做,因为指针现在将指向不同的东西,并且这个指针指向的旧位置没有被删除,现在也没有任何东西指向它(这个是作者如何在不同的章节中解释的)

这是=基类的重载运算符:

baseDMA & baseDMA::operator=(const baseDMA & rs)
{
   if (this == &rs)
      return *this;
   delete [] label;
   label = new char[std::strlen(rs.label) + 1];
   std::strcpy(label, rs.label);
   return *this;
}

接下来,作者定义了一个名为 hasDMA 的派生类,它也new用于pointer-to-char他定义如下的一个:

class hasDMA :public baseDMA
{
private:
    char * style;
    ...
};

hasDMA::hasDMA(const char * s, const char * l)
: baseDMA(l)
{
    style = new char[std::strlen(s) + 1];
    std::strcpy(style, s);
}

现在让我有点困惑的部分是,当作者重载=派生类的运算符时,他似乎没有delete [] style在给它一个新值之前给它一个新值,就像他label对基类所做的那样。这就是作者=为派生类做重载运算符的方式:

hasDMA & hasDMA::operator=(const hasDMA & hs)
{
    if (this == &hs)
       return *this;
    baseDMA::operator=(hs); // copy base portion
    //no delete [] style
    style = new char[std::strlen(hs.style) + 1];
    std::strcpy(style, hs.style);
    return *this;
} 

style就像我们label在分配新值之前从基类中释放指向的内存一样,不释放指向的内存的原因是什么?

提前致谢

4

1 回答 1

6

原因是作者搞错了。这是一个很好的例子,说明你永远不应该管理自己的记忆——他应该std::vector用来管理他的记忆。他没有,因此,他的代码非常错误,如果你模仿他,这正是你的代码将要走的路。

此外,他使用严重过时的自我分配检查不再是成语,并且没有复制和交换。

简而言之,买一本新书。这一切都很糟糕。

于 2013-02-23T19:06:09.323 回答