delete []运算符是否与通过指针返回的动态分配内存一起使用?

时间:2011-09-22 11:57:39

标签: c++ memory-management

我想知道delete []运算符如何通过函数使用指针返回,而不是在与delete语句相同的范围内进行动态分配。假设我有一个像这样的小函数:

int *getArray()
{
    int *returnVal = new int[3];
    returnVal[0] = returnVal[1] = returnVal[2] = 0;
    return returnVal;
}

现在,当我需要在我的代码中使用该数组时,我会执行以下操作:

int *vals = getArray();
// use values...
delete[] vals;

但是,我想知道,C ++编译器如何知道分配的内存块有多大(以及从vals删除多少内存元素)?这是一种有效的技术,还是我必须单独删除每个数组值(如下面的代码所示)?

int *vals = getArray();
// use values...
delete vals + 2;
delete vals + 1;
delete vals;

4 个答案:

答案 0 :(得分:4)

您应该只delete[]通过new[]获得的内容。在您的代码中,getArray()返回的值。删除任何其他内容都是非法的。

  

但是,我想知道,C ++编译器如何知道它有多大   分配的内存块是。

每个实现以某种方式存储分配的大小(以及我认为的类型)。

  • 一个常见的想法是存储簿记信息(或索引 在实际分配的内存之前。
  • 另一个想法是使用实​​际指针作为保存所需信息的数据结构的关键

当然这是过于简单的解释(这更像是对C的解释)。在C ++中,有更多的析构函数和诸如此类的细节。

答案 1 :(得分:2)

从新的[]范围中删除内存是完全可以的。阅读更多here,以下是您懒于查看链接的引用。

  

[16.14]在p = new Fred [n]之后,编译器如何知道删除期间有n个对象被破坏[] p?

     

简短回答:魔术。

     

答案很长:运行时系统存储对象的数量n,   如果你只知道指针,那么它可以被检索到的地方,p。   有两种流行的技术可以做到这一点。这两种技术   正在商业级编译器使用,两者都有权衡,和   既不完美。这些技巧是:

     
      
  1. 过度分配数组并将n放在第一个Fred对象的左侧。
  2.   
  3. 使用关联数组,其中p为键,n为值。
  4.   

答案 2 :(得分:2)

简短的回答:它有效。

事实上,从new[]获得指针的唯一有效方法是delete[]

编译器会将其他信息插入从OS获取的内存中,以允许它跟踪分配的块的大小。此信息允许仅由指针标识的数据被正确销毁和解除分配。

答案 3 :(得分:0)

您不会也不应该依次删除每个元素。你得到未定义的结果。在分配内存时,编译器包括内务处理数据。