我遇到了一个例子:
#include <iostream>
#include <stdexcept>
using namespace std;
class A{
public:
A():m_n(m_object_id++){}
~A(){cout << m_n;}
private:
const int m_n;
static int m_object_id;
};
int A::m_object_id=0;
int main()
{
A * const p = new A[3];
A * const q = reinterpret_cast<A * const> (new char[3*sizeof(A)]);
new (q) A;
new (q+1)A;
q->~A();
q[1].~A();
delete [] reinterpret_cast<char *>(q); // -> here
delete[] p;
cout << endl;
return 0;
}
输出:
34210
有人可以解释delete [] reinterpret_cast<char *>(q); // -> here
,它正在做什么并产生任何输出?
修改
我的问题是delete [] reinterpret_cast<char *>(q);
未调用~A(){cout << m_n;}
,如delete[] p;
,为何如此?
答案 0 :(得分:2)
delete []
为数组的每个元素调用析构函数,然后释放相关的内存。指向数组的指针上的delete
只会调用第一个元素的析构函数,然后释放所有相关的内存。
使用delete []
时始终使用new [..]
。
要调用的析构函数由传递给delete
或delete []
的指针类型决定。在下面的示例中:
A *object1 = new A();
B *object2 = new B();
delete (B*) object1;
delete (A*) object2;
将(可能)导致所有地狱破裂,因为在~B()
的实例上调用A
,反之亦然。
void *object = new A();
delete object;
不会调用~A()
,因为它不知道object
指向A
的实例,而
void *object = new A();
delete reinterpret_cast<A*>(object);
在释放相关内存之前正确调用~A()
。
答案 1 :(得分:2)
q
使用new char[3*sizeof(A)]
的内存初始化,但被视为A
的数组。然后使用此内存在该数组的前两个元素上执行放置new
。
A * const q = reinterpret_cast<A * const> (new char[3*sizeof(A)]);
new (q) A;
new (q+1)A;
在构造元素上显式调用析构函数后,q
将被强制转换回char *
,并使用delete []
删除内存。演员表的目的是确保将delete[]
应用于通过调用new[]
q
所指向的同一类型的对象。
q->~A();
q[1].~A();
delete [] reinterpret_cast<char *>(q); // -> here
必须使用new[]
删除使用delete[]
分配的对象集合。这是因为delete[]
会将指针视为数组分配,并正确地破坏每个数组元素。
答案 2 :(得分:1)
new char[3*sizeof(A)]
说“为我分配足够大的空间以容纳3 As,但将该空间视为字符数组/字符串。”
reinterpret_cast<A * const>
说取你刚刚分配的内存块并将其视为字符串,现在将其视为As的数组。
delete [] reinterpret_cast<char *>(q);
说现在把你现在现在的那块内存想象成As的数组,然后再开始把它想象成一个数组char,因为它是怎么回事已分配,因此必须删除它。 (即delete []将调用该数组中每个字符的char dtor,而不是调用A dtor)
不要在实际代码中执行任何操作!
答案 3 :(得分:0)
p被分配为A类的简单数组,后来被删除。 q更复杂,因为它被分配为原始内存,然后使用placement new在原始内存中创建A的两个元素。这两个元素被单独删除,原始内存将被您要求的语句删除。