这会彻底清除类对象动态分配的结果吗?

问题描述

所以我用这段代码动态分配了一个类对象:

void Inventory::createNewInventoryItem(std::string itemName,unsigned int maxQuantity,unsigned int orderThreshold,double price)
{
    InventoryItems* newItem = new InventoryItems;
    newItem->createInventoryItem(itemName,maxQuantity,orderThreshold,price);
    m_inventory.push_back(newItem);
}

存储在此向量中的内容std::vector<InventoryItems*> m_inventory;

然后一旦对象使用完毕,deleteInventoryItem调用,其定义为:

void Inventory::deleteInventoryItem(int posInVector)
{
    m_inventory.at(posInVector)->~InventoryItems();
    m_inventory.erase(m_inventory.begin() + posInVector);
}

我的问题是:这个deleteInventoryItem函数会成功释放createNewInventoryItem中动态分配使用的内存吗? (这让我对在调用类解构器时是否需要 delete[] 感到困惑)

抱歉不是“关键任务”问题,只是想确保我不会继续不良做法,因为我真的在努力尽可能完美地编程......

解决方法

这个deleteInventoryItem函数会成功释放createNewInventoryItem中动态分配使用的内存吗?

不,您的代码确实会泄漏内存。你在这里做什么,

m_inventory.at(posInVector)->~InventoryItems();

显式调用容器元素的析构函数。这确实会清除特定对象持有的任何资源,但不会清除托管对象本身的内存资源。您必须手动调用对象的析构函数的情况非常非常少(我能想到的唯一情况是使用位置 new,而您很少需要这样做)。

您可以做的是使用 delete 来清理内存调用被擦除元素的析构函数。但是作为这种手动内存管理的更安全的替代方案,我建议您选择以下两个选项之一

  1. 如果应该存储在容器中的对象可以通过值复制(即不是多态类型并且您想存储基类引用),则只需按值存储:

    std::vector<InventoryItems> myData;
    
  2. 否则,存储一个 std::unique_ptr 为您处理所有内存管理:

    std::vector<std::unique_ptr<InventoryItems>> myData;
    
,

不,它会导致内存泄漏。您显然是在调用析构函数,但没有调用 delete 的对应物 newnew 后跟类型首先分配内存,然后隐式调用析构函数。 delete 运算符还做两件事,首先调用析构函数,然后释放内存。

很少需要显式调用析构函数,专门用于清理通过new placement syntax.创建的实例,如果不调用~,这种情况下如果实例包含动态hold会导致泄漏通过成员或基类绑定资源。

根据经验,请记住这些对:

  • obj = new Class; 需要 delete obj;
  • obj = new (buffer) Class 需要 obj->~Class();
  • array = new Class[count]; 需要 delete [] array;

...而且,作为集合中最重要的,自动对象:

  • Class obj; 需要 (nothing) 但是封闭范围的结尾

最后一个“对”显示对(默认)构造函数(它可以是 Class 定义提供的任何其他构造函数)的隐式调用,并以析构函数的隐式调用结束(在右大括号处),顺便说一下,C++ 语言将类的析构函数限制为最多一个的原因是:编译器依赖于这种唯一性能够自动关闭作用域。这种自动性也构成了 std::unique_ptrstd::shared_ptr 的基础。