http://brightli.wordpress.com/2007/03/29/%E6%80%BB%E7%BB%93c%E4%B8%AD%E4%B8%89%E7%A7%8D%E5%85%B3%E4%BA%8Enew%E7%9A%84%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95/
虽然有三种new的用法,但是分为两大类也未尝不可,那么是哪两类呢?
其一是new operator,也叫new表达式;
其二是operator new,也叫new操作符。
其三是placement new, 我觉的就是operator new的overload
这两个英文名称起的也太绝了,很容易搞混,那就记中文名称吧。
new表达式比较常见,也最常用,例如:
string* ps = new string("abc") ;
上面这个new表达式完成了两件事情:申请内存和初始化对象。
new操作符类似于C语言中的malloc,只是负责申请内存,例如:
void* buffer = operator new(sizeof(string)) ;
注意这里多了一个operator。这是new的第二个用法,也算比较常见吧。
那么第三个用法就不很常见了,官方的说法是placement new,它用于在给定的内存中初始化对象,也就是说你手中已有一块闲置的内存,例如:
void* buffer = operator new(sizeof(string)); //那么现在buffer是你所拥有闲置内存的指针
buffer = new(buffer) string("abc"); //调用了placement new,在buffer所指向的内存中初始化string类型的对象,初始值是"abc"
事实上,placement new也是new表达式的一种,但是比普通的new表达式多了一个参数,当然完成的操作和返回值也不同。
因此上面new的第一种用法可以分解两个动作,分别为后面的两种用法。
与new对应的delete没有三种语法,它只有两种,
分别是delete operator和operator delete,也称为delete表达式和delete操作符。
delete表达式和new表达式对应,完成对象的析构和内存的释放操作。而delete 操作符只是用于内存的释放,和C语言中的free相似。例如:
对应第一种
string* ps = new string("abc");
…
delete ps ; //调用delete表达式,先析构再释放
对应第二种
void* buffer = operator new(sizeof(string));
…
operator delete(buffer) ; //释放
那么为什么没有和placement new对应的那个delete呢?
其实是有的。placement new是在指定位置初始化对象,也就是调用了构造函数,因此与之对应的就是析构函数了,只不过它不叫placement delete而已。
对应第三种
void *pv = operator new(sizeof(vector<int>));
pv = new(pv) vector<int>(8, 0);
…
static_cast<vector<int>* >(pv)->~vector(); // call destruct function
operator delete(pv); // free memory
pv = NULL;
[注] 参考自more effective C++
一个网上的例子,
#include <iostream>
using namespace std;
// operator new example
#include <iostream>
#include <new>
using namespace std;
class myclass
{
public:
myclass() {cout <<"myclass constructed/n";}
~myclass(){cout <<"myclass destructed/n";}
};
int main () {
int * p1 = new int;
// same as:
// int * p1 = (int*) operator new (sizeof(int));
int * p2 = new (nothrow) int;
// same as:
// int * p2 = (int*) operator new (sizeof(int),nothrow);
myclass * p3 = (myclass*) operator new (sizeof(myclass));
// (!) not the same as:
// myclass * p3 = new myclass;
// (constructor not called by function call, even for non-POD types)
new (p3) myclass; // calls constructor
// same as: the same as?, constructor is not called
// operator new (sizeof(myclass),p3);
delete p3;
// same as:
// p3->~myclass();
// operator delete(p3);
// myclass obj;
myclass *pobj = new myclass;
pobj->~myclass();
return 0;
}