Is it necessary to overload placement new operator, when we overload new operator?
I have below piece of code
class Test
{
public:
Test(){}
开发者_如何学JAVA Test(int i) {}
void* operator new (size_t size)
{
void *p = malloc(size);
return p;
}
//void* operator new (size_t size, Test *p)
//{
// return p;
//}
};
int main() {
Test *p = new Test;
int i = 10;
new(p) Test(i);
}
Above piece of code does not compile in visual studio, unless i uncomment out the overloaded placement new operator function. If i comment out normal overloaded new, in that case also it works fine. Is overloading of placement new mandatory when overloading normal new operator(If placement new need to be used for that class)
Placement delete related code is not shown here.
Usually no, since it's not often used. But it might be necessary, since when you overload operator new
in a class, it hides all overloads of the global ::operator new
.
So, if you want to use placement new on objects of that class, do; otherwise don't. Same goes for nothrow
new.
If you've just changed the allocation scheme, and you're surprised that someone somewhere is using placement new behind your back, that might be something to investigate before applying this band-aid.
If the class is used inside standard library containers, not directly with new
, the custom allocation scheme should be defined by an Allocator class, not an overload. The default allocator std::allocator
does not respect member operator new
overloads, but bypasses them. See below.
Disclaimer: class-scope operator new
overloads are mainly useful for debugging, and even then it's tricky to get reliably meaningful semantics. Beware:
You need to also overload
operator delete
. (Not done in the example in this question.)Overloads will be bypassed by the qualified syntax
::new T
. You cannot prevent such bypassing. This is the way thatstd::allocator<T>
allocates things. You can specializestd::allocator
for your types, but that's some way into the rabbit-hole already.For each
::operator new
overload introduced by any library, including the canonical placement new from<new>
, you will have to consider whether it applies to your class and decide whether to add an overload, or otherwise contend with the failure of unqualifiednew
expressions.For each
::operator new
you adopt into your class, you must supply the corresponding member placementoperator delete
with correct semantics. This is called in case the constructor exits by exception. Failing to have it would result in a memory leak only under very specific circumstances, in a possibly resource-constrained pool.
In summary, member operator new
is the antithesis of defensive coding.
Placement new operator doesn't exist by default for a class so when you're making a call to new(p) Test(i);
C++ compiler can't find a definition of the commented function in the above example. If you uncomment the placement operator new for your class, and comment out the "normal" one then the default "normal" new operator will be used and your code will compile.
implementations of std::_Construct use the global placement new. So concerns about STL compatability should not be concerns. But the concern about breaking existing code, that may have been written
new ((void*)p) thing;
rather than
::new ((void*)p) thing;
is certainly a valid point.
精彩评论