以下代码为B**
创建双指针B*
。它将使用该指针为另一个指针分配内存,该指针将指向调用B
时创建的start()
实例:
class A
:
class A
{
public:
A()
{
fb = new B*;
*fb = NULL;
}
~A()
{
if(*fb)
delete *fb;
delete fb;
}
B** getfb()
{
return fb;
}
private:
B** fb;
};
class B
:
class B
{
public:
B()
{
B** fb = a->getfb();
*fb = this;
}
~B()
{
B** fb = a->getfb();
delete *fb; // <--- stack overflow
*fb = NULL;
}
private:
A* a;
};
start()
(class C
的成员函数):
void C::start()
{
B** fb = a->getfb(); // 'a' is a pointer to an 'A' instance
if(*fb == NULL)
B* f = new B;
}
因此,每当我调用start()
然后调用~B()
时,我都会出现堆栈溢出!
答案 0 :(得分:7)
听起来不错。
fb
的类型为B**
,因此*fb
的类型为B*
。
所以当你说delete *fb
你正在调用class B
的析构函数时,这是一个递归调用,它没有向基本情况发展,因此堆栈溢出。
答案 1 :(得分:6)
在B()
中,您指定*fb = this;
,然后指定:
~B()
{
...
delete *fb; // delete this;
...
}
..相当于一次又一次地在析构函数delete this;
内调用~B()
,因此由于递归函数过多而导致堆栈流。
这是Is it safe to delete this
的一个很好的主题。
答案 2 :(得分:4)
这并不奇怪。你在B类的析构函数中,访问当前正在调用析构函数的B的SAME实例,然后再次删除它。这将导致析构函数调用中的递归,从而导致堆栈溢出。你在A类中删除fb足以清理你的记忆,你不希望B类自行删除。
您也不需要在B类构造函数中执行您正在执行的操作。你在A级的代码是有道理的,你在B级所拥有的代码是危险的和不必要的。在B类中,您无法设置其成员a。这意味着指针未初始化,然后尝试将此B类实例分配给此未初始化 A实例的B类成员指针。
B()
{
B** fb = a->getfb(); // a never gets set to a meaningful value!!!!!
*fb = this;
}