开发者

Is it necessary to overload placement new operator, when we overload new operator?

开发者 https://www.devze.com 2023-01-14 07:17 出处:网络
I have below piece of code class Test { public: Test(){} 开发者_如何学JAVATest(int i) {} void* operator new (size_t size)

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 that std::allocator<T> allocates things. You can specialize std::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 unqualified new expressions.

  • For each ::operator new you adopt into your class, you must supply the corresponding member placement operator 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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号