理解'delete []':C ++

时间:2013-06-28 01:48:10

标签: c++ dynamic-allocation

我遇到了一个例子:

#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;,为何如此?

4 个答案:

答案 0 :(得分:2)

delete []为数组的每个元素调用析构函数,然后释放相关的内存。指向数组的指针上的delete只会调用第一个元素的析构函数,然后释放所有相关的内存。

使用delete []时始终使用new [..]

要调用的析构函数由传递给deletedelete []的指针类型决定。在下面的示例中:

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的两个元素。这两个元素被单独删除,原始内存将被您要求的语句删除。