删除运算符和数组?

时间:2010-01-06 11:23:03

标签: c++ arrays memory-management

我有一个abstract Base班级和Derived班级。

int main ()
{
  Base *arrayPtr[3];

  for (int i = 0; i < 3; i++)
  {
    arrayPtr[i] = new Derived();
  }

  //some functions here

  delete[] arrayPtr;

  return 0;
}

我不确定如何使用delete运算符。如果我删除了如上所示的基类指针数组,那么这会调用派生类对象的析构函数并清理内存吗?

11 个答案:

答案 0 :(得分:10)

不,您必须明确删除数组中的每个项目:

for (int i = 0; i < 3; ++i)
{
    delete arrayPtr[i];
}

答案 1 :(得分:10)

您必须迭代数组的元素delete如果数组已使用delete []动态分配,请在数组上调用new[]

在示例代码中,数组已在堆栈上分配,因此您不能在其上调用delete []

还要确保您的Base班级有virtual析构函数。

参考:When should my destructor be virtual

答案 2 :(得分:2)

你应该这样做:

 for ( int = i; i < 3; i++ )
 {
    delete arrayPtr[i];
 }

当你试图释放/删除分配了delete[] arrayPtr;的堆栈时,你不应该arrayPtr

要考虑的另一件事是使用std::vector指针而不是数组。如果您使用的是实现TR1的编译器,您也可以使用std::vector std::tr1::shared_ptr而不是原始指针,而不必担心自己删除这些对象。

示例:

{
    std::vector< std::tr1::shared_ptr<Base> > objects;
    for (int i=0; i < 3; ++i)
    {
        objects.push_back(std::tr1::shared_ptr<Base>(new Derived()));
    }
}  // here, once "objects" exit scope, all of your Derived objects are nicely deleted

答案 3 :(得分:1)

您必须单独删除阵列的成员。您还必须确保您的基类具有虚拟析构函数。您可能还想考虑将其设置为智能指针的数组(或更好的std :: vector),例如boost :: shared_ptr。

答案 4 :(得分:1)

不,你不能这样做。正如其他人建议您必须浏览每个项目并将其删除。记住这是一个非常简单的规则。如果您使用new分配,则使用delete,如果您使用了new[],则使用delete[]

答案 5 :(得分:1)

注意缺席的是什么:

int main() {
  boost::ptr_vector<Base> v;
  for (int i = 0; i < 3; i++) v.push_back(new Derived());
  // some functions here, using v[0] through v[2]
}

检查Boost's pointer containers

答案 6 :(得分:1)

操作员删除必须与该指针上的operator new匹配,如果它已分配new[],则必须调用delete[],反之亦然;

int* pInt = new int;
delete pInt; OK
delete [] pInt; WRONG

int[] pIntArr = new int[3];
delete [] pIntArr; OK
delete pIntArr; WRONG

在你的情况下还有其他错误 - 你正在尝试在堆栈上分配的delete。那不行。

在这种特殊情况下,您必须单独删除每个指针。

答案 7 :(得分:1)

你有什么未定义的行为 - 一个错误。每次拨打new都需要与delete匹配;每次拨打new[]都需要与delete[]匹配。两者是分开的,不能混合。

在您发布的代码中,您有一个指向堆栈上Base的指针数组。然后你在堆栈上分配的数组上调用delete[] - 你不能这样做。您只能delete[]使用new[]在堆上分配的数组。

对于使用delete分配的每个元素,您需要调用new - 或者最好使用容器类(例如std::vector)而不是使用数组。

答案 8 :(得分:0)

确保Base有一个虚拟析构函数。然后像fretje outlined一样删除数组中的每个元素,然后删除数组。

您应该使用std::vector作为数组。也就是说,你应该真的使用为这类东西制作的容器。 (所以你不会意外地删除所有元素,如果抛出异常肯定会出现这种情况!)Boost有such a library

答案 9 :(得分:0)

不,这不是你想要的。

这里有两点需要注意:

  1. 如果动态分配数组,则使用语法delete[] arrayPtr,如下所示:

    arrayPtr = new (Base *)[mylength];
    

    但是,在您的情况下,您有一个静态分配的数组,因此无需删除它。但是,您需要删除数组中的各个元素:

    for ( int = i; i < 3; i++ )
         delete arrayPtr[i];
    
  2. 您需要注意的第二点是使类Base的析构函数为虚拟:

    class Base
    {
        virtual ~Base();
        /* ... */
    };
    

    这可确保当您在Base *上调用实际指向Derived的删除时,会调用Derived的析构函数,而不仅仅是Base的析构函数

答案 10 :(得分:0)

您正在混合范例 - 数组删除运算符旨在释放由数组new运算符分配的内存,但您将堆栈上的数组作为指针数组分配,然后为每个数组成员分配一个对象。在您的代码中,您需要遍历数组。

要使用数组new运算符,您将声明如下:

Base *array;
array = new Base[3];
/* do stuff */
delete[] array;

这为三个对象分配了一个连续的内存区域 - 请注意,你有一个Base对象数组,而不是一个指向Base对象的数组。