Deleting an aliased pointer
Doing this:
union{
int * integer;
char * character;
} u;
u.integer = new in开发者_如何学Pythont;
delete u.character;
u.integer = new int[5];
delete [] u.character;
I assume this wouldn't work if any of these types have non trivial destructors, but is this ok?
This doesn't work in any case, if we assume work means having well-defined behavior rather than appearing to work (i.e. not crashing)
No, this is undefined behavior regardless of whether or not the item has a trivial destructor. If the destructor is trivial it may appear to "work" when in fact it's leaking memory, etc.
I'm going to say this is somewhere between implementation defined and undefined.
5.3.5/2: "In the first alternative (delete object), the value of the operand of delete may be ... a pointer to a non-array object created by a previous new-expression ... .
The value of the pointer does not change when used the way you did so, so this should work as expected, provided sizeof(char*) == sizeof(int*)
. The result of that particular comparison is implementation defined, and if the assumption is false then the behavior is undefined.
So it really really isn't particularly safe.
It is easy to see this is a dangerous error. The two types might have completely different and incompatible ways of memory allocation and deallocation. This includes padding, garbage collection, bookkeeping, class-specific memory manipulation, etc. Just don't do it.
#include <cstddef>
#include <cstdlib>
#include <iostream>
using namespace std;
class A
{
public:
void* operator new (size_t size)
{
cout << "A::operator new (size_t)" << endl;
return malloc(size);
}
void* operator new [] (size_t size)
{
cout << "A::operator new [] (size_t)" << endl;
return malloc(size);
}
void operator delete (void* ptr)
{
cout << "A::operator delete (void*)" << endl;
free(ptr);
}
void operator delete [] (void* ptr)
{
cout << "A::operator delete [] (void*)" << endl;
free(ptr);
}
};
class B
{
public:
void* operator new (size_t size)
{
cout << "B::operator new (size_t) with some B-specific stuff" << endl;
return malloc(size);
}
void* operator new [] (size_t size)
{
cout << "B::operator new [] (size_t) with some B-specific stuff" << endl;
return malloc(size);
}
void operator delete (void* ptr)
{
cout << "B::operator delete (void*) with some B-specific stuff" << endl;
free(ptr);
}
void operator delete [] (void* ptr)
{
cout << "B::operator delete [] (void*) with some B-specific stuff" << endl;
free(ptr);
}
};
int main (int, char**)
{
union{
A* a;
B* b;
} u;
u.a = new A();
delete u.b;
u.a = new A[5];
delete [] u.b;
}
精彩评论