C++: overriding new & delete
整理自:Thinking in C++
1. Intro
When you create a new
-expression such as new T
, two things occur:
- storage is allocated using
operator new
, - then the constructor is called.
In a delete
-expression such as delete pt;
:
- the destructor is called,
- then storage is deallocated using
operator delete
.
The constructor and destructor calls are never under your control, but you can overload the storage allocation parts of new
and delete
.
When you overload operator new
, you also replace the behavior when it runs out of memory, so you must decide what to do in your operator new
:
- return zero, or
- write a loop to call the
new_handler
and retry allocation, or - (typically) throw a
bad_alloc
exception
Digress: set_new_handler()
当 new
申请不到内存的时候,其实是会执行一个叫做 new_handler
的 function,这是一个无参的 void 函数,默认的行为是 throw 一个 exception。我们可以用 #include <new>
的 set_new_handler()
函数来设置一个新的 new_handler
,只要这个 new_handler
是一个无参的 void 函数就行。看例子:
#include <iostream>
#include <cstdlib>
#include <new>
using namespace std;
int count = 0;
void out_of_memory() {
cerr << "memory exhausted after " << count
<< " allocations!" << endl;
exit(1);
}
// DANGEROUS. Better try it on a virtual machine
int main() {
set_new_handler(out_of_memory);
while(1) {
count++;
new int[1000]; // Exhausts memory
}
}
The behavior of the new_handler
is tied to operator new
, so if you overload operator new
, the new_handler
will not be called by default. If you still want the new_handler
to be called you’ll have to write the code to do so inside your overloaded operator new
.
2. Overriding global new
& delete
- The overloaded
new
takes an argument ofsize_t
, and return avoid*
. - The
operator delete
takes an argument ofvoid*
, and returns avoid
.
下面给个没有啥实际意义的例子,主要是演示怎么写:
#include <cstdio>
#include <cstdlib>
void* operator new(size_t sz) {
printf("operator new: %d Bytes\n", sz);
void* m = malloc(sz);
if(!m) {
puts("out of memory");
}
return m;
}
void operator delete(void* m) {
puts("operator delete");
free(m);
}
Notice that printf()
and puts()
are used rather than iostream
. This is because when an iostream
object is created, it calls new
to allocate memory–it’a deadlock.
3. Overriding new
& delete
for a class
Although you don’t have to explicitly say static
, when you overload new
and delete
for a class, you’re creating static
member functions.
例子见书上 P620
4. Overriding new
& delete
for arrays
重载 operator new[]
和 operator delete[]
,语法和前面一样,只是 operator new[]
的参数 (size_t size)
是 size of the entire array。
例子见书上 P624
5. Placement new
首先声明一点:placement new
并不是指传 additional parameter 给 new
,而是利用 new
可以接受 additional parameter 这个特性来实现 construct an object on memory that’s already allocated,i.e. 用 already allocated memory 来 replace new
出来的 memory。
new
接收 additional parameter 的语法是:
T::operator new(size_t, ...) {
...
}
T* pt = new(...) X(1024);
有啥新添的参数,在 new
object 的时候全部加到 new
的括号里。
关于 placement new
,可以参阅:
- 深入探究 C++ 的 new/delete 操作符
- What uses are there for “placement new”?
- FAQ: What is “placement new” and why would I use it?
注意销毁 placement new
出来的对象需要显示调用 destructor pt->T::~T();
,也只有这里会这么用。详情请看书或者看上述的参考链接。
Comments