【问题标题】:How do you delete a pointer to a vector of pointers in c++?如何在 C++ 中删除指向指针向量的指针?
【发布时间】:2020-06-24 21:55:48
【问题描述】:

假设在 A 类中,我有一个指向向量的指针,其中包含指向 B 类的指针

Class A {
    ....
    std::vector<B *>* table;
    ....
}

Class B {
     int var1;
     int var2;
     B (const int _var1, const int _var2){
          var1 = _var1;
          var2 = _var2;
     }
}

如何在 A 类的析构函数中删除表?

我试过了

    ~A()
    {
        for (int i = 0; i < table->size(); i++)
        {
            delete (*table)[i];
        }
        delete[] table;
    }

但由于某种原因,它在析构函数中给出了段错误。

感谢您的帮助!

【问题讨论】:

  • 您可能不尊重rule of 3/5/0,但我们无法判断,因为您没有提供minimal reproducible example。请注意,几乎没有理由拥有指向向量的指针(指向向量的指针需要确保获得deleted)。你可能只想要std::vector&lt;B&gt; table;。过度使用指针是 c++ 中的一个常见错误。
  • 为什么A首先存储一个指向向量的指针?我认为您应该摆脱示例中的所有指针。
  • 首先确保没有创建指向指针向量的指针。
  • 我可以看到指向指针的问题,让我看看我是否可以简化该实现
  • @BlueXhusky 的经验法则 - 使用new 分配的内存必须使用delete 释放,使用new[] 分配的内存必须使用delete[] 释放。不要混合它们。更好的经验法则 - 在 C++11 及更高版本中,根本不要手动使用 new/delete,而是使用智能指针(std::unique_ptrstd::shared_ptr)并让它们处理所有的释放你。

标签: c++ pointers destructor


【解决方案1】:

你的段错误是由这一行引起的:

delete[] table;

告诉编译器你想删除一个数组。 table 不是一个数组,虽然它可能表现得像它,但它是一个指向堆上 single 对象的指针,并且调用 delete[](而不是 delete)因此会导致未定义的行为.

根据经验,永远不要使用裸指针。如果您确实使用裸指针,请始终对 delete 使用与 new 相同的形式。

正如 cmets 中所指出的,在现代 C++ 中,您应该永远拥有一个装满裸指针的容器(裸指针是不由使用 RAII 的包装器对象管理的指针)。

因此,您应该在向量中使用std::unique_ptr&lt;B&gt;std::shared_ptr&lt;B&gt; 代替B*。您也不应该有std::vector 指针,而应该将向量复制或移动(如果复制成本很高)到位。使用智能指针而不是裸指针,希望不会再次发生:p。

【讨论】:

  • 感谢您的智能指针建议。我意识到复制不必那么广泛,并设法找到一个不涉及指针的解决方案。
  • 所有权使事情复杂化并且有点超出了这个答案的范围(哈哈),而当你知道它指向的对象也会比它寿命更长时,裸指针是可以接受的,那么它们就可以了,但是手动应该几乎永远不要使用new'ing和delete'ing(这就是我所说的'使用智能指针')
【解决方案2】:

由于您的析构函数中的 delete[] table 语句,您遇到了分段错误。

delete[] table; 替换为delete table;

【讨论】:

  • 使用错误的delete 与释放已释放的内存不同。请记住,delete 不是freedelete 最终会导致内存被释放,但它也会结束对象的生命周期并调用析构函数。
  • 它实际上并没有释放已经释放的内存,它试图删除你不拥有和/或与table无关的内存。
  • @TheGoldKnight23 你能解释一下你是怎么得出这个结论的吗?
  • delete[] 将删除当前指针,然后查找数组的其他元素,即使它们不存在。这意味着当它在单个指针上被调用时,它会大肆破坏,因为它永远不会找到数组的边界,并且对于此时发生的事情完全没有定义
  • @TheGoldKnight23 当您使用错误的delete 时,可能会发生这种情况。这是未定义的行为。没有任何一种可能的结果比其他任何结果都更有效。有时它可能工作得很好。它可能不会崩溃和损坏一堆数据。它甚至可能在到达delete 之前崩溃。假设 UB 将如何表现是不正确的。
猜你喜欢
  • 2010-09-08
  • 1970-01-01
  • 1970-01-01
  • 2019-09-10
  • 2013-04-14
  • 1970-01-01
  • 1970-01-01
  • 2011-08-04
  • 1970-01-01
相关资源
最近更新 更多