删除C++中的继承类指针数组

Delete Inherited class Pointer Array in C++

本文关键字:指针 数组 继承 C++ 删除      更新时间:2023-10-16

我有一个A类,比如:

class A
{
int a;
}

而且,我也有继承A类的B类:

class B : public A
{
int b;
public:
static A** ReturnAPtrArray(int size);
}

然后,我使数组在类 B 中具有 A 类指针。

A** B::ReturnAPtrArray(int size)
{
A** array = new A*[size];
for(int i = 0; i< size; i++)
{
array[i] = new A();
}
return array;
}

在 main func 中,我调用了类 B 的 ReturnAPtrArray(( func。

void main(void)
{
int size = 100;
A** aptrArray = B::ReturnAPtrArray(size);
--------Do Something
delete[] aptrArray;
}

这个主要功能使内存泄漏。所以我删除了像这样的每个指针:

void main(void)
{
int size = 100;
A** aptrArray = B::ReturnAPtrArray(size);
--------Do Something
for(int i = 0; i< size; i++)
{
delete aptrArray[i];
}
delete[] aptrArray;
}

修改主函数后,内存泄漏消失了。

如果我想释放内存,我应该删除指针数组中的所有指针吗?

还有其他选择吗?

如果我想释放内存,我应该删除指针数组中的所有指针吗?

是的,你应该

delete[]仅删除它自己的数组。 由于您有一个指针数组,因此必须单独删除每个指针元素。

至于其他选项,您可以使用智能指针。

例:

#include <memory>
#include <vector>
int main()
{
std::vector<std::shared_ptr<A>> array;
for(int i = 0; i < 100; i++)
{
array.push_back(std::make_shared<B>());
}
}

当数组超出范围时,它会自行删除它

区分多态所有权和多态使用很重要。多态所有权是指您想要拥有未知类型的事物(或许多事物(。多态性使用是指当你不知道一个东西是什么时,你想操纵它。你的例子并没有真正说明你为什么使用继承,所以我将解释两者。

如果您只创建 B,只需将它们声明为 B。如果你想将一组 B 传递给一个不知道它们是 B 的函数,只需创建一个 B 的向量并将它们作为指向 A 的指针传递。
喜欢这个。。。

std::vector<B> myBs(5);   // create 5 default B's
for (const auto& thisB: myBs) Fn(&thisB); // cast a ptr-to-B to a ptr-to-A

像这样保持简单会让你的生活简单得多,因为这段代码是类型安全的。

另一方面,如果你想拥有一个可能是B的东西列表,也可能不是,但肯定是从A继承的。

std::vector<std::unique_ptr<A>> my_maybe_bs_might_not;

这种模式表面上看起来更简单,但它有很多陷阱。例如,您必须使用必须使用虚拟设计器。这反过来又调用了 3/5 规则。简单地说,如果编译器不知道一件事,你必须告诉它如何移动/复制它。如果你不这样做,编译器可能会做错事。

一个更简单的(假设你有 C++17(的多态所有权方案是使用变体。当您使用变体时,您必须列出它可能的所有内容,这可以包括智能指针。

using MaybeB = std::variant<std::unique_ptr<B>, std::unique_ptr<C>>;
std::vector<MaybeB> my_maybe_bs_might_not;

此模式允许编译器为您生成所有正确的代码,同时使添加新类变得简单。唯一的缺点是,因为您必须列出您可能想要拥有的所有东西。这使得它成为库级系统的糟糕选择,其中库的用户可能希望编写自己的类(派生自 A(并将其添加到您的列表中。

一般的建议是尽可能选择最简单的方案,这通常意味着避免多态所有权,除非确实需要。