Ioannis Vranos said:
David said:
The above is generally not portable because of alignment issues. This is
more portable:
int main()
{
unsigned char* garbage = new unsigned char[sizeof(SomeClass)];
SomeClass *t = new(garbage) SomeClass;
t->~SomeClass();
delete[] garbage;
}
What alignment issues? I can't see any difference between the two forms.
Alignment is a hairy issue. The link that I provided discussed it a little
bit. It's also discussed in the FAQ in 11.10. In a nutshell, functions
like malloc() and the allocation functions in C++ (3.7.3.1) are required to
return a pointer that can be converted to a pointer of any complete object
type and dereferenced, used, etc. If you simply have a locally defined
array of unsigned char, there is no such requirement that it must work. In
the above code, I'd probably avoid the usage of unsigned char and simply use
operator new, the bad_alloc-throwing C++ memory allocation function that
resembles malloc, directly.
References on "placement operator delete":
C++2003 18.4.1.3
TC++PL 3: Page 576, 19.4.5.
VS help says about the placement delete form:
"The second function is called by a placement delete expression
corresponding to a new expression of the form new(std::size_t). It does
nothing."
In another place:
"The second and third forms of this operator will commonly not be called
from code but exist to give the compiler a matching delete to call when
a placement new fails."
So if I got it right, placement delete does not do anything if it not
explicitly defined, but is provided as a match when exceptions are
thrown etc.
So indeed we have to call the destructor explicitly. However experiments
with my compilers puzzle me.
Oh, placement _operator_ delete. When people refer to "placement new"
they're usually referring to what the standard calls a "new expression"
(e.g. new (pointer) Type()), and not operator new, so I assumed you were
referring to some unusual "delete expression". The wording's a bit tricky,
but there is a difference. You're not calling placement operator delete in
the above code. As you can see in the standard, placement operator delete
"intentionally performs no action". I'm not really sure why things are the
way they are, but you can see that the placement operator news and placement
operator deletes do nothing. I suspect that they exist to make the wording
in other parts of the standard easier on the reader.
Yes, you're right, you need to call the destructor explicitly. The code "T*
p = new T();" performs two major steps: it allocates storage for an instance
of T and (assuming the allocation succeeded and the constructor exists) it
invokes the constructor for T. In the code you provided, step 1 was
unnecessary, so all that is needed to "clean up" is a call to the
destructor.