New
的
3
种形态:
new operator
、
operator new
、
placement new
new
操作符
(new
表达式
, new
operator
, new expression):
通常我们调用
X * pX = new X
时使用的就是这个操作符
,
它由语言内建
,
不能重载
,
不能改变其行为
.
它包括分配内存的
operator new
和调用构造函数的
placement new
。
new
关键字实际上做了三件事:获得一块内存空间、调用构造函数、返回正确的指针。当然,如果我们创建的是简单类型的变量,那么第二步会被省略。
operator new :
operator new
是一个函数
, void *
operator new(size_t size)
。它分配指定大小的内存
,
可以被重载
,
可以添加额外的参数
,
但第一个参数必须为
size_t
。
operator new
除了被
new operator
调用外也可以直接被调用
: void * rawMem =
operator new(sizeof(X))
。这种用法和调用
malloc
一样。
placement new :
placement new
在一块指定的内存上调用构造函数
,
包含头文件
<new>
之后也可以直接使用
placement new: X * pX = new (rawMem) X
。
与
new operator
类似
,
对于
delete
operator,
也存在
operator
delete: void operator delete(void *),
析构方法
pX->~X().
New
的基本使用指南:
想在堆上建立一个对象,应该用
new
操作符。它既分配内存又为对象调用构造函数。如果仅仅想分配内存,就应该调用
operator new
函数;它不会调用构造函数。如果想定制在堆对象被建立时的内存分配过程,你应该写你自己的
operator new
函数,然后使用
new
操作符,
new
操作符会调用定制的
operator new
。如果想在一块已经获得指针的内存里建立一个对象,应该用
placement
new
。
placement new
主要适用于:在对时间要求非常高的应用程序中,因为这些程序分配的时间是确定的;长时间运行而不被打断的程序;以及执行一个垃圾收集器
(garbage collector)
。
由于
placement new
的特殊性,下面给出其常规使用步骤:
class Task ; //
char * buff =
new char[sizeof(Task)]; // 1)
分配内存
Task *ptask =
new(buff) Task
;
// 2)
构造对象
ptask->suspend();
// 3)
正常使用对象
ptask->resume();
ptask->~Task();
//
4)
析构对象
delete [] buff;
// 5)
释放内存
显然,
placement new
可以提高效率,但增加了程序的复杂度,需要自行管理对象的生存期。
Placement new
的使用大量存在于
STL
中。