I\'m dang certain that this code ought to be illegal, as it clearly won\'t work, but it seems to be allowed by the C++0x FCD.
class X { /* ... */};
void* raw
The Standard rules at [basic.stc.dynamic.deallocation]p3
Otherwise, the value supplied to
operator delete(void*)
in the standard library shall be one of the values returned by a previous invocation of eitheroperator new(size_t)
oroperator new(size_t, const std::nothrow_t&)
in the standard library, and the value supplied tooperator delete[](void*)
in the standard library shall be one of the values returned by a previous invocation of eitheroperator new[](size_t)
oroperator new[](size_t, const std::nothrow_t&)
in the standard library.
Your delete
call will call the libraries' operator delete(void*)
, unless you have overwritten it. Since you haven't said anything about that, I will assume you haven't.
The "shall" above really should be something like "behavior is undefined if not" so it's not mistaken as being a diagnosable rule, which it isn't by [lib.res.on.arguments]p1. This was corrected by n3225 so it can't be mistaken anymore.
I found this in the library section of the standard, which is about as counter-intuitive a location (IMO) as possible:
C++0x FCD (and n3225 draft) section 18.6.1.3, [new.delete.placement]
:
These functions are reserved, a C ++ program may not define functions that displace the versions in the Standard C ++ library (17.6.3). The provisions of (3.7.4) do not apply to these reserved placement forms of operator new and operator delete.
void* operator new(std::size_t size, void* ptr) throw();
void* operator new[](std::size_t size, void* ptr) throw();
void operator delete(void* ptr, void*) throw();
void operator delete[](void* ptr, void*) throw();
Still, the section defining legal expressions to pass to delete
is 5.3.5, not 3.7.4.
I suppose you might get away with it (on a particular compiler) if
new
/delete
are implemented in terms of malloc
/free
and new
actually uses the same mechanism for keeping track of the destructor associated with allocations as the standard new
, so that the call to delete
could find the right destructor. But there is no way it can be portable or safe.
The compiler doesn't really care that p
comes from a placement new
call, so it won't prevent you from issuing delete
on the object. In that way, your example can be considered "legal".
That won't work though, since "placement delete
" operators cannot be called explicitly. They're only called implicitly if the constructor throws, so the destructor can run.