简体   繁体   中英

Understanding 'delete []' : C++

I came across an example:

#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;
}

the output: 34210

Can someone explain delete [] reinterpret_cast<char *>(q); // -> here delete [] reinterpret_cast<char *>(q); // -> here , what it is doing and producing any output?

EDIT

My question is delete [] reinterpret_cast<char *>(q); not calling ~A(){cout << m_n;} , like delete[] p; , why so ?

delete [] calls the destructor for each and every element of the array, then frees the associated memory. delete on a pointer to an array would only call the destructor of the first element, then free all associated memory.

Always use delete [] when you use new [..] .

The destructor to be called is determined by the type of the pointer passed to delete or delete [] . In the sample below:

A *object1 = new A();
B *object2 = new B();

delete (B*) object1;
delete (A*) object2;

Will (potentially) cause all hell to break loose, because ~B() is being called on an instance of A and vice-versa.

void *object = new A();
delete object;

does not call ~A() because it doesn't know object points to an instance of A , whereas

void *object = new A();
delete reinterpret_cast<A*>(object);

does correctly call ~A() before freeing the associated memory.

q is initialized with memory from new char[3*sizeof(A)] , but is being treated as an array of A . This memory is then used to perform placement new on the first two elements of that array.

A * const q = reinterpret_cast<A * const> (new char[3*sizeof(A)]);
new (q) A;
new (q+1)A;

After explicitly calling the destructors on the constructed element, q is cast back to a char * , and the memory is deleted with delete [] . The purpose of the cast is to make sure that delete[] is being applied to the same type of object that was created with the call the new[] to which q points.

q->~A();
q[1].~A();
delete [] reinterpret_cast<char *>(q); // -> here

The collection of objects that were allocated with new[] , must be deleted with delete[] . This is because delete[] will treat the pointer as an array allocation, and properly destruct each array element.

new char[3*sizeof(A)] says "allocate me some space big enough for 3 As, but think of that space as a char array/string."

reinterpret_cast<A * const> says take that block of memory you just allocated and are think ing of as a string, and now think of it as an array of As.

delete [] reinterpret_cast<char *>(q); says now take that block of memory which you are now thinking of as an array of As, and start thinking of it as an array char again, because that how it was allocated, so that's how it has to be deleted. (ie, the delete[] will call the char dtor on each char in that array rather than called the A dtor)

Don't do any of that in real code!

p is being allocated as a simple array of class A, and is later deleted. q is more complex, because it is allocated as raw memory, and then two elements of A are created within that raw memory using placement new. Those two elements are individually deleted, and the raw memory is deleted by the statement you are asking about.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM