【问题标题】:Deleting a vector of pointers passed to a class删除传递给类的指针向量
【发布时间】:2013-02-17 22:11:31
【问题描述】:

我有一个抽象的module 类,特定模块派生自该类。在运行时,我会解析一个配置文件并确定配置文件中每个模块的具体模块类型:

std::vector<module*> modules;
module *temp;

//Let nm be the result of parsing as a std::string

if(nm == "type1")
{
    temp = new module_1(...);
}
else if(nm == "type2")
{
    temp = new module_2(...);
}
else if(nm == "type3")
{
    temp = new module_3(...);
}
else
{
    //Syntax error
    return -1;
}

modules.push_back(temp);
partition p;
p.modules = modules;

将向量 modules 传递给 partition 类:

class partition
{
    public:
    //Member functions

    private:
    //...Other variables
    std::vector<module*> modules;
};

用完这些模块指针后,为这些模块指针释放内存的正确方法是什么?我试图在 partition 类的析构函数中删除它们,如下所示,但最终出现了分段错误:

partition::~partition()
{
    for(unsigned i=0; i<modules.size(); i++)
    {
         delete modules[i];
    }
}

【问题讨论】:

  • 您为什么决定使用std::vector&lt;module*&gt; 而不是std::vector&lt;module&gt;
  • @LihO 我假设他正在使用虚函数。
  • @Adam27X 我的直接猜测是您正在双重删除您的模块。使用私有复制构造函数来禁止复制。
  • @Lalaland 我的直接想法也是,除了在那种情况下,他不应该得到双重释放/堆损坏错误吗?至少在 gcc 中,这些与段错误不同。
  • 你用gdb看过这个吗?它死在哪里?

标签: c++ memory-management memory-leaks


【解决方案1】:

这取决于您希望如何处理所有权以及分区是否将具有值语义。想想如果你复制一个分区会发生什么:

分区的副本是否会与原始分区共享模块。模块中的更改是否要在分区之间共享?

如果是,您应该为您的分区使用std::shared_ptr。所有的痛苦都消失了。

如果没有,请为您的分区实现一个复制构造函数和赋值运算符,以执行模块列表的深拷贝。实现一个析构函数,删除列表中的每个模块。这是安全的,因为每个分区都有自己的模块对象。

总的来说,我赞成第二种方法。如果您不想实现深度复制,只需将partition 设为不可复制或仅移动并使用std::unique_ptr 处理删除。

【讨论】:

  • 我确实将partition 类的一个实例传递给另一个类package。然后将package 类的一个实例传递给与其中的模块一起工作的一些线程。每个分区都有自己的一组模块,因此第二种方法似乎相关。对于这种情况,我是否也需要为 package 类提供深层副本?
  • @Adam27X 模块对象是否是线程安全的(即多个线程可以使用同一个模块对象)?
  • @WhozCraig 是的。一个给定的模块本身永远不会被多个线程访问,但在我的代码的当前状态下,每个线程确实可以访问所有模块,即使它只会使用它们的特定子集。
  • 如果每个线程都可以访问分区中的所有模块,并且只使用它需要的模块,实际上会更容易。如何设置互斥完全是另一项任务。但是shared_ptr 而不是unique_ptr 可能更好地服务于分区的复制性质(以及它正在提升的模块表)(假设我正确理解了这个问题)。无论哪种方式,pmr 的答案(这个)都是准确的。
  • @WhozCraig 这很大程度上取决于您是否将module 视为一个值或一个对象,以及应该如何传播一个模块中的更改。无论如何:层次结构中的一个深拷贝就足够了。
猜你喜欢
  • 2012-01-05
  • 2012-06-01
  • 2020-03-27
  • 2021-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-12
  • 2013-09-24
相关资源
最近更新 更多