【问题标题】:How to properly free a set of pointers?如何正确释放一组指针?
【发布时间】:2019-12-29 21:48:00
【问题描述】:

如果我有一个像 std::set 这样的容器,其中包含指向动态对象的指针,那么我该如何释放它的元素?

int main()
{

    // new scope
    {
        int x = 10;
        std::set<int*> spi;
        spi.insert(new int(1));// elem is a dynamic object init from 1
        spi.insert(new int[3]()); // elem is a dynamic array of 3 default-init integers
        spi.insert(&x); // elem is address of stack memory object
    }
}

那么我怎样才能有效地释放具有动态内存的元素呢?

  • 我知道我可以使用一组 shared_ptrs 或 unique_ptr,但为了练习,我想知道如何使用。

【问题讨论】:

  • 您应该在单独的集合中跟踪您手动分配的内存。
  • 有效释放一组指针的正确方法是使用一组智能指针。
  • 哦,你不能像这样在std::set 中混合数据类型和分配策略,这是一个非常糟糕的主意。

标签: c++ dynamic-memory-allocation stdset


【解决方案1】:

您必须遍历容器的内容并释放与每个元素对应的内存。

for ( auto ptr : spi )
{
   delete [] ptr;
}

但是,请记住,您发布的代码存在问题。不能delete 使用addressof 运算符获得的指针。如果您尝试在容器的所有元素上调用delete,以下行将导致下游问题。

spi.insert(&x);

避免将此类混合指针放入容器中。您无法知道使用new 分配了哪个元素,使用addressof 运算符获得了哪个元素。

不仅如此,如果在容器中添加new int(10)new int[3]获取的指针,无论在容器的元素上使用delete还是delete []都会遇到未定义的行为。其中一个会出错。

我的建议是尝试编写干净的代码,而不是尝试寻找创造性的方法来处理编写不佳的代码。

【讨论】:

  • 不会删除x 的指针导致未定义的行为吗?
  • @DanielA.White 是的,它会的。
  • 另外new int(1) 需要一个没有[] 的普通delete
  • @HolyBlackCat,真是一团糟:) :)
【解决方案2】:

如果您将非拥有指针放入集合中,那么合理的方法是将集合专门用于非拥有指针。因此,动态对象必须由其他一些数据结构拥有。一个例子:

int x = 10;
auto y = std::make_unique<int>(1); // the dynamic object is owned by smart pointer
std::vector<int> z(3);             // the dynamic array is owned by vector

std::set<int*> spi;
spi.insert(y.get());
spi.insert(z.data());
spi.insert(&x);

【讨论】:

    【解决方案3】:

    没有办法。

    您无法分辨每个指针指向什么(堆栈上的对象、堆上的对象还是堆上的数组?),因此无法知道如何正确处理它们。


    您必须以相同的方式分配每个元素,以便可以以相同的方式处理它们,或者存储有关每个元素的一些附加信息。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多