C++ 从堆空间删除对象

C++ 从堆空间删除对象,c++,heap-memory,C++,Heap Memory,在main函数中,我使用new创建了一个对象,而不是删除它。我希望一旦进程退出,堆空间就会被清除。下面是一个示例代码,其中类a的对象是类B的成员变量。类B也有一个multimap作为成员变量 Class A { Public: A(); //have definition in cpp file ~A();//have definition in cpp file Private: Int a; }; Class B{

在main函数中,我使用new创建了一个对象,而不是删除它。我希望一旦进程退出,堆空间就会被清除。下面是一个示例代码,其中类a的对象是类B的成员变量。类B也有一个multimap作为成员变量

    Class A
    {
    Public:
    A(); //have definition in cpp file
    ~A();//have definition in cpp file
    Private:
    Int a;
    };

    Class B{
    Private:
    Std::multimap<string,string> map_test;
    Public:
    A a;
    B(); //have definition inn cpp file
    ~B();//does not have any definition in cpp file
    };

    int main()
    {
      B *b = new B();
      /* code section where it fills some 1000 key value pairs in the multimap 
         for some purpose */
      return 0;

    }
A类
{
公众:
A();//在cpp文件中有定义
~A();//在cpp文件中有定义
私人:
INTA;
};
B类{
私人:
Std::多重map试验;
公众:
A A;
B();//在cpp文件中具有定义
~B();//在cpp文件中没有任何定义
};
int main()
{
B*B=新的B();
/*代码部分,其中它填充多重映射中的大约1000个键值对
出于某种目的*/
返回0;
}
我的理解是:

  • 即使我不在这里删除对象,也不会产生任何问题,因为一旦进程退出,堆空间将被清理。因为我的程序范围如上所述是有限的,没有其他人会重用它。所以不使用delete是好是坏?你对此有什么建议
  • 它应该调用对象的默认析构函数,然后调用隐式多重映射析构函数。所以不需要明确清除多重映射。如果我错了,请纠正我
  • 在父类中,它只是声明析构函数,没有任何定义。因此它将调用隐式析构函数还是忽略调用它?(没有理由不定义它,只是为了更好地理解。)
  • 如果它在父类的情况下调用隐式析构函数,它应该调用这里定义的子类析构函数吗
  • 由于父类对象是使用new实例化的,它将在堆中创建。然后,该父类对象的成员变量将存储在什么位置。例如,对象“a”是一个成员变量,通过查看该成员对象的声明,它似乎将在堆栈中创建。在这里,我很困惑父对象和它的成员子对象是如何精确创建内存的。你能帮我理解这一点吗

  • 你问了很多问题

    首先,它的最佳实践是总是清除内存,即使进程退出并清除所有内存(正如它所做的那样)。始终处理它..使用共享\u ptr很容易做到


    析构函数总是以正确的顺序被调用,但是多重映射是一个危险的程序,因为你应该清除多重映射中的元素,因为如果你存储指针,它可能会导致严重的泄漏

    你问了很多问题

    首先,它的最佳实践是总是清除内存,即使进程退出并清除所有内存(正如它所做的那样)。始终处理它..使用共享\u ptr很容易做到

    析构函数总是以正确的顺序被调用,但是多重映射是一个危险的程序,因为你应该清除多重映射中的元素,因为如果你存储指针,它可能会导致严重的泄漏

  • 是的,只要您的对象是在main中创建的。 然而,如果您想要改变这一点,例如创建多个B实例,或者在另一个类中使用它,那么情况就不同了。此外,像valgrind这样的内存检查工具将在新的w/o删除上提供误报,您可能会忽略它。但是,如果真正的内存泄漏成为一种习惯,您可能会忽略它

  • 正确,现在如果它是一张
    地图
    ,那么您可能需要清理

  • 它将调用默认析构函数

  • 是的,会的

  • 我猜,您是在问基类成员变量存储在哪里?它们也存储在堆上。它们位于内存中派生类字段的前面

  • 是的,只要您的对象是在main中创建的。 然而,如果您想要改变这一点,例如创建多个B实例,或者在另一个类中使用它,那么情况就不同了。此外,像valgrind这样的内存检查工具将在新的w/o删除上提供误报,您可能会忽略它。但是,如果真正的内存泄漏成为一种习惯,您可能会忽略它

  • 正确,现在如果它是一张
    地图
    ,那么您可能需要清理

  • 它将调用默认析构函数

  • 是的,会的

  • 我猜,您是在问基类成员变量存储在哪里?它们也存储在堆上。它们位于内存中派生类字段的前面

  • 大多数操作系统会在进程退出时清理进程的堆空间。如果有很多嵌入式操作系统不是这样的话,我也不会感到惊讶,而且这仍然是一个糟糕的做法,因为你确实有内存泄漏
  • 当你泄漏内存时,不会调用析构函数。也就是说,如果您没有实现析构函数,并且依赖于编译器生成的默认析构函数,那么也不应该声明它-事实上,我很惊讶您没有得到链接器错误。是的,multimap的默认析构函数将删除multimap的内容,只要您遵守容器对值语义的要求(即,没有原始指针)
  • 这是一种糟糕的做法,作为一名程序员,你应该确保你总是正确地管理你的资源。另外,我看不出堆分配
    b
    的任何理由,您只需在堆栈上创建对象,就不必考虑资源管理
  • 如果您确实声明了它,则必须提供一个实现,因为析构函数的声明将隐式禁用编译器生成的析构函数。这就是为什么我在上面说,我很惊讶你没有得到一个链接错误
  • 编译器将通过遍历层次结构并按与构造相反的顺序调用析构函数来处理基类的销毁
  • 不,包含A和B的整个对象都将在堆上构造-这就是为什么可以使用别名