A* p = new A[5];
delete &p[2];
//错误,为什么?是否需要使用delete []p
一起删除?
p是指针(p == &p[0]
),但是,p [0],p [1] ...是一种对象。为什么p [n]不是指针?
答案 0 :(得分:2)
会实现什么?你试图释放单个A的空间,在一个较长的连续A阵列中间的某个地方。
这根本不起作用,因为它反对delete
所做的事情。
执行new[]
时,运行时会为您提供足够大的内存集来存储对象数组。如果那个记忆不是四十四岁的话。无论如何,运行时要求操作系统将内存页面映射到您的进程中。记忆空间。
现在,如果您不再使用这些页面,您可以"给他们回复&#34 ;;但是,你必须对你得到的整个记忆块做到这一点。这是因为释放少于一页不能工作(因为操作系统无法在其他地方分配),并且因为允许这种碎片会使页表巨大
这反映在free
的文档中:您只能通过free
将malloc
提供给您的完全相同的地址来释放记忆。
答案 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
的指针}。