c++ - 什么时候在堆中的对象上调用 C++ 析构函数?

标签 c++ pointers vector memory-leaks

假设一个类及其用法

#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/

相关文章:

c++ - 导致断点的 window

c++ - 使用 std::find() 搜索多个元素

c# - 在 Unity C# 中将对象缓慢移动到新位置

c++ - typedef 默认模板类型为同名

c++ - 如何访问使用 omp_target_alloc() 分配的设备内存

c++ - 我可以轻松地覆盖 (STL) 迭代器的类别吗?

java - 用java实现 vector 的程序

c++ - iostream 的确切含义是与 ios_base::sync_with_stdio 同步

c - C 中的数组很麻烦

c - 指针和函数外部分配或静态变量和内部分配?