我想知道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;
答案 0 :(得分:4)
您应该只delete[]
通过new[]
获得的内容。在您的代码中,getArray()
返回的值。删除任何其他内容都是非法的。
但是,我想知道,C ++编译器如何知道它有多大 分配的内存块是。
每个实现以某种方式存储分配的大小(以及我认为的类型)。
当然这是过于简单的解释(这更像是对C的解释)。在C ++中,有更多的析构函数和诸如此类的细节。
答案 1 :(得分:2)
从新的[]范围中删除内存是完全可以的。阅读更多here,以下是您懒于查看链接的引用。
[16.14]在p = new Fred [n]之后,编译器如何知道删除期间有n个对象被破坏[] p?
简短回答:魔术。
答案很长:运行时系统存储对象的数量n, 如果你只知道指针,那么它可以被检索到的地方,p。 有两种流行的技术可以做到这一点。这两种技术 正在商业级编译器使用,两者都有权衡,和 既不完美。这些技巧是:
- 过度分配数组并将n放在第一个Fred对象的左侧。
- 使用关联数组,其中p为键,n为值。
醇>
答案 2 :(得分:2)
简短的回答:它有效。
事实上,从new[]
获得指针的唯一有效方法是delete[]
。
编译器会将其他信息插入从OS获取的内存中,以允许它跟踪分配的块的大小。此信息允许仅由指针标识的数据被正确销毁和解除分配。
答案 3 :(得分:0)
您不会也不应该依次删除每个元素。你得到未定义的结果。在分配内存时,编译器包括内务处理数据。