最近在看C++ Prime,注意到new 和 delete 并没有原来想象的那么简单。记得上学期学C语言时,学习的sizeof和strlen区别时,有一条为sizeof不是函数在这里,和sizeof类似,new 和delete也不是函数,它们都是C++定义的关键字,通过特定的语法可以组成表达式。我们先看看上面提到的operator new 和 operator delete在C++语言标准库的原型
void *operator new(size_t); //allocate an object
void *operator delete(void *); //free an object
这两个均是 C++ 标准库函数!C++ Primer 一书上说new 和 delete是不允许重载的,那么这里就不是重载 new 和 delete 表达式(如 operator=就是重载 = 操作符),那么
operator new 和 new operator到底有什么区别呢?
new operator:
string *ps=new string("linux");
它完成了两件事情
void * operator new (size_t size);
其返回类型void*。即返回一个指针,指向一块原始的、未设置初始值的内存。函数中的size_t参数表示需要分配多少内存,你可以将operator new 重载,加上额外的参数,但第一个参数类型必须总是size_t。可以像调用任何其他函数一样调用它。
void* rawMemory=operator new(sizeof(string));
这里的operator new 将返回指针,它指几一块足够容纳string对象的内存。和malloc一样,operator new 的唯一任务就是分配内存,它不知道什么是构造函数,它只负责分配内存。取得operator new 返回的内存并将之转为一个对象,是new operator的工作。这样,刚才的那段代码
string *ps=new string("linux");
可以这样理解
void* memory=operator new(sizeof(string)); //取得原始内存,用于放置一个string对象
call string::string("linux") on *memory;//将内存中对象初始化
string *ps=static_cast(memory); //让ps指向新完成的对象
但是在查资料时,还发现了另一个迷惑的术语
placement new 有时候想直接调用一个构造函数,针对一个已经存在的对象调用其构造函数,并无意义,因为构造函数用来对象初始化,而对象只能只能初始化一次。但是当需要在一些分配好的原始内存上构建对象时,placement new,允许这么做。
class Test
{
public:
Test(int Size);
......
};
Test* constructTestInBuffer(void *buffer,int size)
{
return new (buffer) Test(size);
}
此函数返回指针,指向一个Test对象,它被构造于传递给此函数的一块内存缓存区上。当程序运行到共享内存或者内存I/O映射。这类函数可能是有用的,
void * operator new(size_t size,void* location)
{
return location;
}
operator new 的目的是要为对象找到一块内存,然后返回一个指针指向它,在placement new 的情况下,调用者已经知道指向内存的指针了,因为调用
operator new 对于new operator一样。
string *ps;
...
delete ps; //使用delete operator.
内存释放动作是由operator delete执行的,通常声明如下:
void operator delete(void* );
因此 delete ps;
void* buffer=operator new (50*sizeof(char));//分配内存,放置50个char,没有调用构造函数
...
operator delete(buffer); //释放内存,而没有直接调用析构函数。
类似与C语言中malloc和free。
void * mallocShared(size_t size);//申请分配内存
void freeShared(void * momery);//释放内存
void* sharedMemory=mallocShared(sizeof(Test));
Test *pw=constructTestBuffer(sharedMemory,10);//使用前面Test类的placement new
...
delete pw;//无定义,因为sharedMemory来自mallocShared,不是来自new
pw->~Test();//OK,析构函数pw所指Test对象,但并释放Test所占用内存。
freeShared(pw);//OK,释放pw所指的内存,不调用任何析构函数。
如上述所示,如果交给placement new的原始内存(raw memory)本身是动态分配而得的,那么最终得释放那块内存,以避免内存泄露
string *ps=new string[10];//分配一个对象数组
1.这里的new 与前面的new 行为类似,但略有不同,这里不能再operator new分配内存,而是以operator new[]负责分配。和operator new 一样,operator new[]也可以被重载。
string *ps=new string[10];//调用operator new[]以分配足够容纳10个string对象的内存,然后针对每个元素调用string的默认构造函数。
同样的,当使用了delete,它也会针对数组中每一个元素调用析构函数,然后再调用operator delete[]释放内存。如:
delete []ps;//为数组中的每一个元素调用string 析构函数,然后再调用 operator delete[] 释放内存。跟operator delete一样 operator delete[]也可以被重载。