假设一个类及其用法
#include <vector>
class B
{
public:
B() {temp = 0;}; // implemented
~B() {} ; // implmented
private :
int temp;
// it holds a std::bitset , a std::vector.. It is quite large in size.
};
class A
{
private:
std::vector<B*> * _data ;
public:
A()
{
_data = new std::vector<B*>(0);
}
~A()
{
for(unsigned int idx_ = 0; idx_ < _data->size(); ++idx_)
delete _data->at(idx_);
delete _data ;
}
void addB()
{
B * temp = new B();
_data->push_back(temp);
}
}
int main()
{
A temp;
temp.addB();
// Do something
}
我的问题是这段代码会泄漏内存吗?还假设另一种用法
int main()
{
A * temp = new A();
temp->addB();
delete temp ; // 1
}
这里需要1吗?如果我有一个指向堆的指针并且该指针超出范围,则在堆中的元素上调用析构函数。我只想确定这一点。 谢谢!
最佳答案
为了更容易关联什么时候调用析构函数,什么时候不调用,使用这个经验法则:当一个对象的内存被回收时,对象的析构函数就会被调用(并且内存被正确回收之后)。
您的第一个示例不会泄漏任何内存。 这就是为什么……您基本上创建了 2 个对象。
A 和 B。
A 在堆栈上。对象 A 的内存是在堆栈上隐式创建的。
B 是由您的代码显式在堆上创建的。
当 main() 返回时,堆栈上的每个对象都被销毁。即,用于保存堆栈上对象成员的内存(在本例中为对象 A)正在被隐式回收。由于对象 (A) 实际上正在被销毁并回收其内存,因此调用 A 的析构函数。
在 A 的析构函数中,您明确告诉运行时回收代码明确分配的所有内存(即,当您调用 delete 时)。因此对象 B 的内存也被回收了。
因此没有泄漏。
在第二个示例中,您再次创建了 2 个对象 A 和 B。 在这里,两个对象的内存都驻留在堆中。这是由您的代码使用 new 运算符显式分配的。 在这种情况下,您的代码永远不会回收为 A 分配的内存。即永远不会为 A 调用 delete。
main() 的堆栈只包含指向 A 的指针的内存。main() 堆栈本身不包含 A 的内存。所以当 main() 返回时,所有被销毁的是之前的内存分配给 指向 A 的指针,而不是 A 本身。 由于 A 的内存从未被回收,因此它从未被“销毁”。因此它的析构函数从未被调用,相应地“B”也从未被销毁。
关于c++ - 什么时候在堆中的对象上调用 C++ 析构函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33861023/