我正在阅读C ++ Primer Plus书的第13章。 它有一个例子,它涉及使用继承与动态内存分配,复制构造函数和重载=运算符。
基类(称为baseDMA
)有一个私有指针到char,它在构造函数中使用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
指向的内存,然后再为它赋值一样?
提前致谢
答案 0 :(得分:6)
原因是作者犯了一个错误。这是一个很好的例子,说明你应该如何管理自己的记忆 - 他应该使用std::vector
来管理自己的记忆。他没有,因此,他的代码非常错误,而且如果你模仿他,这正是你的代码将要去的方式。
此外,他使用严重过时的自我分配检查不再是一个成语,而且没有复制和交换。
简而言之,获得一本新书。这一切都很糟糕。