如何删除类内部类类型的类成员指针
Posted
技术标签:
【中文标题】如何删除类内部类类型的类成员指针【英文标题】:How to delete a class member pointer of the class type inside the class 【发布时间】:2018-06-12 04:22:55 【问题描述】:我有一段代码如下:
class Base
public:
Base()
Base(int in);
virtual ~Base() delete b_;
private:
Base *b_;
int in_;
;
class Derived : public Base
public:
Derived()
~Derived()
;
Base::Base(int i) : in_(in)
b_ = new Derived();
int main()
Base *b = new Base(1);
delete b;
return 0;
我在删除 Base 中的 b_ 时遇到了分段错误,我猜原因是因为它最终会导致对 ~Base() 的无限递归调用。我也尝试在 main() 中调用 ~Derived() 然后删除 b,但是由于 b_ 没有释放,仍然存在内存泄漏。
所以我的问题是,如果我有这样的代码,那么释放所有内存的正确方法是什么。我已经搜索了几个小时的解决方案,但没有得到任何令人满意的结果。所以任何建议都会有所帮助,谢谢。
【问题讨论】:
为什么基类型会知道派生类型? 每个Derived
拥有另一个Derived
。那是不可能的。
@codekaizer 感谢您的指出,我已经说得更清楚了。代码是从一个相当复杂的系统中抽象出来的。它的设计只是因为系统需要它。为什么它有这个要求完全不在当前话题......
我可能会注意到问题的一部分是你有一个虚拟析构函数~Base()
,它被非虚拟~Derived()
覆盖。老实说,我很惊讶甚至允许这样做。
“在 Base 中删除 b_ 时出现分段错误” - 你是怎么猜到的?您是否设法使用调试器介入其中?因为您显示的代码会在调用任何析构函数之前很久就导致分段错误。
【参考方案1】:
在基类中添加另一个函数
delete b_;
在破坏 b 之前在 main() 中调用它可以解决问题。
编辑:
经过半天的工作,我终于得出以下结论:
-
问题中发布的代码使用 GCC 编译和运行,但如果我使用 mac 的集成编译器 (clang) 编译它然后运行,则会出现分段错误。
1. 的原因是删除
~Base()
内的b_
是一个递归调用,最终会在某个时候删除一个未初始化的指针(一些未初始化的b_
)。如果使用 GCC 编译,编译器(或至少我的编译器)会将 b_
初始化为 nullptr
(我知道根据 c++ 标准,b_
的默认值是未定义的),这就是程序正常结束的原因。但是对于 clang,b_
没有被编译器赋予任何特定的默认值,所以我得到了分段错误。
一种解决方法是默认将b_
设置为nullptr
(在Base
的默认构造函数中)并在~Base()
中添加类似这样的内容:if (b_ != nullptr) delete b_;
【讨论】:
它不能解决问题。它使症状消失。以上是关于如何删除类内部类类型的类成员指针的主要内容,如果未能解决你的问题,请参考以下文章