为什么我不能单独从对象数组中删除指针?

时间:2015-04-19 11:04:52

标签: c++

A* p = new A[5];
delete &p[2];

//错误,为什么?是否需要使用delete []p一起删除?

p是指针(p == &p[0]),但是,p [0],p [1] ...是一种对象。为什么p [n]不是指针?

4 个答案:

答案 0 :(得分:2)

会实现什么?你试图释放单个A的空间,在一个较长的连续A阵列中间的某个地方。

这根本不起作用,因为它反对delete所做的事情。

执行new[]时,运行时会为您提供足够大的内存集来存储对象数组。如果那个记忆不是四十四岁的话。无论如何,运行时要求操作系统将内存页面映射到您的进程中。记忆空间。

现在,如果您不再使用这些页面,您可以"给他们回复&#34 ;;但是,你必须对你得到的整个记忆块做到这一点。这是因为释放少于一页不能工作(因为操作系统无法在其他地方分配),并且因为允许这种碎片会使页表巨大

这反映在free的文档中:您只能通过freemalloc提供给您的完全相同的地址来释放记忆。

答案 1 :(得分:2)

您删除的内容必须与您分配的内容完全匹配,您不能进行部分删除。内存管理器通常根据返回的地址记录有关分配的信息。如果您将其他地址传递给delete,则无法找到分配信息。

答案 2 :(得分:1)

是和否:

,拨打new[]的电话必须与delete[]的一次通话配对。

,不会“一起删除”,因为结果只是一个实体(数组),而不是A的集合。因此,您实际上并没有删除任何内容。

,您无需同时结束阵列中所有元素的生命周期。但是,显式调用析构函数是您可能希望在此时留给标准库组件的内容。

这将我们带到:

您似乎想要实现的目标:
结束该数组的单个对象的生命周期。由于结果是带有某种魔法漏洞的数组没有任何意义,你可能需要考虑std::vector<A>::erase来处理它。这将移除一个元素并向上移动所有其他元素,以便结果表现得像一个数组,其中一个元素已被移除而没有留下任何漏洞。

答案 3 :(得分:0)

delete适用于指针(仅指向动态分配的内存块的指针),但您没有指针数组,因此delete不会&#39} ; t对数组元素起作用,它只能对数组指针起作用。它应该是delete []运算符。

如果要从数组中删除元素,则必须迭代数组,当到达要删除的元素时,请开始使用下一个元素覆盖数组。此外,您可能希望分配一个新的较短的数组,并在那里执行该操作,然后删除旧数组并将数组指针设置为新数组。

理想情况下,你应该使用std::vector类,它会自动为你完成所有事情:

std::vector<A> v(5); // gives you a vector of 5 A elements
v.erase(v.begin() + 2); // erases the element at index 2

这种方式不容易出错并且是首选,并且与容易出错的手动方式一样快速有效。

现在,如果您有一个指向元素的指针的数组/向量,那将是另一回事,那么您必须确保delete元素擦除它来自矢量。当然,如果你使用智能指针,你可以简单地从向量中删除指针,它将自动删除

  

为什么p [n]不是指针?

指针的[n]运算符只是一个快捷方式,用于指向带有偏移量的指针。因此p[2]相当于*(p + 2)。当你取消引用一个指针时,你得到一个引用它指向的东西,在你的情况下是一个A实例。所以delete p[2]只有在它是一个A指针数组而不是A实例时才能工作。请注意,在您的情况下,&p[2]实际上是指针,它与p + 2的值相同,因为&运算符将获取引用的地址,但应该不使用delete,因为它本身并不指向动态分配的内存,即使它本身恰好存在于这样的内存中。

正如您在p == &p[0]问题中所指出的那样,p != p[0]。这意味着即使两者都是指向同一地址的指针,也不应该delete &p[0]。由于数组的内存已分配new [],因此应使用delete []取消分配,并且不应在数组或其任何元素上使用delete运算符。

&p[0]为您提供数组中第一个元素的地址,该元素与数组的开头重合,但p == &p[0]只是一个值比较。 p可能等于&#34;到&p[0],但在语义上不一样,因为p是指向A []的指针,&p[0]是指向A的指针}。