1 两种new的区别和联系
C++中的操作符new在执行下面代码时,做了如下两件事。这种操作符叫做"new operator"。对于开辟空间这部分,new operator实际调用了operator new操作符。
1 调用operator new操作符,开辟内存空间。
2 调用构造函数,初始化内存空间。
class MyClass {
}
MyClass *my = new MyClass;
程序员无法重载new operator,但是可以重载operator new,即空间分配函数。
operator new函数通常声明为如下形式——其必须制定分配内存大小。该函数返回一个指针,指向未初始化的内存。size_t指定了内存大小。
void * operator new(size_t size);
void *rawMemory = operator new(sizeof(string));
// init the memory
string *ps = static_cast<string*>(rawMemory);
2 Placement new
不仅分配内存可以手动定制,初始化内存依然可以手动定制。我们调用类的构造函数,并将原始内存初始化,这种行为被称为placement new。
如下代码所示,其调用new operator,来对已经开辟的内存buffer进行初始化。
class MyClass {
public:
MyClass(int param);
}
MyClass *createMyClass(void *buffer, int param) {
return new (buffer) MyClass(param);
}
实际上,new operator隐式调用operator new,利用operator new返回的指针,来进一步调用构造函数来初始化内存。
因此,我们可以定义如下operator new操作符——不开辟空间,直接利用传入的指针。注意,operator new 操作符必须给出第一个内存大小参数。
void * operator new(size_t, void *location) {
return location;
}
placement new技术在#include < new >或#include <new.h> 中声明。
3 析构与内存释放
创建对象顺序是:开辟空间,初始化内存。删除对象的顺序就要相反。与new相对应,delete也有两种类型的操作符:delete operator 和 operator delete。delete operator调用operator delete来释放空间。
1 调用析构函数
2 删除开辟的内存空间
但是,由于内存空间是由operator new获得的,因此在释放内存时,就不能用经过类型转换的指针,而是使用原始的内存指针。
void *rawMemory = operator new (10 * sizeof(string));
// do something
operator delete(rawMemory);
4 数组
C++相应提供了operator new []和 operator delete[] 操作符用于重载。这两个操作符用于开辟数组空间。
对于new [] operator 和 delete [] operator而言,其调用顺序与单个对象一致,只是在初始化或析构内存空间时,需要为数组中的每个对象执行构造或析构函数。