为什么要重载 operator new

这里可以先参考

array new / array delete

因为使用默认的 global operator new , 会附带有额外的开销,而通过自定义的 member function operator new, 我们可以改变内存分配机制。

<aside> 💡 全局的 global operator new 也可以重载,但比较少见

</aside>

重载 global operator new

void* myAllow(size_t size) { return malloc(size); }
void* myFree(void* ptr) { return free(ptr); }

// 不能声明在一个 namespace 中
inline void* operator new(size_t size) { return myAlloc(size); }
inline void* operator new[](size_t size) {return myAlloc(size); }
inline void operator delete(void* ptr) { myFree(ptr); }
inline void operator delete[](void* ptr) { myFree(ptr); }

重载 member operator new

class Foo {
 public:
  static void* operator new(size_t);
	static void operator delete(void*, size_t);  // size_t: optional
  static void* operator new[](size_t);
	static void operator delete[](void*, size_t);  // size_t: optional
	// ...
}

Foo *p = ::new Foo(7);  // 使用这种方式可以强制使用 global operator new
::delete p;

<aside> 💡 cpp 里默认这4个方法都是 static, 所以写不写static都可以。这是因为如果不是 static,那么调用对应的方法就需要通过一个对象来调用,但此时就是在处于一个创建对象的过程中,就会产生矛盾。

</aside>

重载placement new

class Foo {
 public:
  static void* operator new(size_t);
	static void operator delete(void*, size_t);  // size_t: optional
  static void* operator new[](size_t);
	static void operator delete[](void*, size_t);  // size_t: optional
	// ...

	static void* operator new(size_t, char);  // 可以作为被重载的 placement new. (1)
	
	// 我们也可以重载 class member operator delete(), 写出多个版本,但它们绝对不会被 delete 调用
  // 只有当 new 所调用的 ctor 抛出了异常之后,这些重载版的 operator delete() 才有机会被调用
  // 主要用来归还对应的 placement new 分配所得的内存
	// 即时 operator delete() 未能一一对应于 operator new(), 也不会出现任何的报错:即说明放弃处理 ctor 发出的异常
	static void operator delete(void*, char);  // 与上面的 (1) 对应
}

// 调用方式如下
Foo* pf = new(300, 'c') Foo;