谈谈new 与delete

任何一个C++程序员对这两个运算符都很熟悉,不就是生成和释放一个对象嘛。但是当我们需要自己管理对象的内存分配行为时,有必要好好讨论一番。先介绍一下几个概念:

1.        内存申请

new operator: 如 string *ps = new string(“Memory Management”);

上述语句做了两方面的工作:第一,分配了一个足够存放一个string对象的内存;第二,调用string类的constructor,为string对象设定初值。至于想自己管理对象的内存分配策略,就得重载operator new,但第二步却不能够改变,也不应该改变。

operator new: 我们可以重载operator new来改变用来容纳对象的内存的分配行为。函数operator new 通常声明如下:

void * operator new(size_t size);

其返回值为void *,指向一块raw memory,参数size表示分配多少内存。

重载之后你也可以直接调用operator new如下:

void *rawMemory = operator new(sizeof(string));

这本质上和使用 void *rawMemory = malloc(sizeof(string));一样,只负责了内存的分配。

从上面的new operator和operator new 分析中,可以看出:

string *pStr = new string(“hello”);

实际上会进行的动作可分解为:

1 void *rawMemory = operator new(sizeof(string));//分配原始内存

2 调用constructor 初始化rawMemory     

3 string *ps = static_cast<string*>(memory);  //让pStr 指向新完成的对象

下面谈谈new operator 的另一种用法,称为placement new,当程序使用共享内存或内存映射机制时,这类函数可能是有用的。下面我们来看看他的真面目,范例如下:

string * constructStringInBuffer(void*buffer, int size)    //返回内存地址

{

       returnnew (buffer) string(size);

}

上述中的new (buffer) string(size)是new operator 的用法之一,在STL中的容器alloctor中被广泛使用。

总结一下上述new operator, operator new 及placement new 的区别:new operator 用于在堆中生成对象,而placement new是new operator的一种用法,用于在一块已知的内存中构造对象, operator new 只是分配了内存,并不会调用对象的构造函数。

2.        内存释放

既然申请了内存,当然还要关心会不会产生内存泄露。内存释放动作是由函数operator delete执行,通常声明如下:

void operator delete(void *memory);

而执行delete pStr;相当于执行

ps->~string();

operator delete(ps);    //从这边也可以看出operator delete与operator new是配套的

这边表明了如果你不打算调用对象的析构函数来释放内存,就应该用operator delete来处理operator new 生成的内存。

需要注意的是如果你使用placement new,你应该避免对那块内存调用 delete operator,(因为要析构对象); 但是同样你也不能通过直接调用delete pStr; (调用析构函数后调用operator delete)。因为对象使用的内存并不来自operator new.这时就应该手动释放。范例如下:

void * mallocShare(size_t size);

void * freeShared(void*memory);   //这一对函数配套使用,用于申请和释放内存

void *shareMemory = mallocShare(sizeof(string));

string *pStr = constructStringInBuffer(shareMemory,sizeof(string));

pStr->~string();

freeShard(pStr);

参考资料:More Effective C++

原文地址:https://www.cnblogs.com/OpenLinux/p/5020704.html