more-effective-c++ 序列1 new和delete的测试

来源:互联网 发布:有向网络最短路径 编辑:程序博客网 时间:2024/06/02 13:13

more-effective-c++ 序列1 new和delete的测试


1,在堆内存中分配对象,而且欲对堆内存的分配使用自己的方式。

Widget *pWidget = new Widget():
1,调用operator new 分配内存
2,将内存上的对象调用构造函数
3,转换为Widget*赋值给pWidget
故而可以通过重写operator new 和delete来自己决定内存分配方式。


下面的代码在operator new中调用的malloc,在operator delete 调用的free。
当然你甚至可以使用内存池的观点,operator new调用GetMemory, operator delete调用ReturnMemory.
这样可以个性化自己的内存分配方式。
#include <iostream>using namespace std;/*new operator会调用operator new和Widget的构造函数重载operator new和delete可以订制自己的行为。*/#define TRACE_FUCTION_AND_LINE(fmt, ...) printf("[%20s:%4d]"fmt"\n",__FUNCTION__, __LINE__, ##__VA_ARGS__)class Widget{public:Widget(){TRACE_FUCTION_AND_LINE();}void* operator new(size_t nSize){void*p =  malloc(sizeof(Widget));TRACE_FUCTION_AND_LINE("malloc p=%08p", p);return p;}void operator delete(void* memory){TRACE_FUCTION_AND_LINE("free p=%08p", memory);free(memory);}~Widget(){TRACE_FUCTION_AND_LINE();}};int main(){Widget *pWidget = new Widget();TRACE_FUCTION_AND_LINE("begin to delete");delete pWidget;return 0;}





2. 打算在已经分配的内存上分配对象,使用placement new的方式



下面的代码main函数中,首先分配了一个栈内存buf,然后赋值给memory指针。
然后调用new (memory)Widget(100)将memory指针传递到operator new 方法。
由于operator new是为了分配内存的,现在已经有一个栈内存了,可以直接拿来使用,故而直接return buffer;
然后会调用Widget的构造函数初始化对象。打印日志后需要执行调用对象的析构函数。
如果不主动调用析构函数,那么对象的析构函数就不会被调用。
也许你会问,为什么不调用delete pw来释放内存呢?你可以尝试一下,由于operator delete默认会采用delete方式delete内存,这样实际上delete的是
栈内存memory,这会立刻出现问题。


main函数下面注释的一段代码仅仅是个人对new,operator new,malloc三种内存分配和释放方式的简单测试,就想看看哪个效率更高一点。
测试例子不够完善,一般的内存使用方案的分配和释放都是随机的,这个例子不是,不能准确的反映现实数据,但至少说明了malloc似乎更快一点。

#include <iostream>#include <time.h>using namespace std;/*new operator会调用operator new和Widget的构造函数重载operator new和delete实现placement new*/#define TRACE_FUCTION_AND_LINE(fmt, ...) printf("[%20s:%4d]"fmt"\n",__FUNCTION__, __LINE__, ##__VA_ARGS__)class Widget{public:Widget(int nHight = 0): m_nHight(nHight) {TRACE_FUCTION_AND_LINE();}void* operator new(size_t nSize, void* buffer){TRACE_FUCTION_AND_LINE("malloc p=%08p", buffer);return buffer;}~Widget(){TRACE_FUCTION_AND_LINE();}void Log () {TRACE_FUCTION_AND_LINE("My Log------%d", m_nHight);}int m_nHight;};int main(){char buf[sizeof(Widget)]; //分配栈内存void* memory = buf;//分配widget内存,实际上使用的是栈内存TRACE_FUCTION_AND_LINE("memory = %08p", memory);Widget* pw = new (memory)Widget(100); //placement new 将memory指针传递到operator newpw->Log();pw->~Widget();//主动调用析构函数/*double start, end;while(1){start = clock();for(int i = 0; i < 500; ++i){for(int j = 0; j < 10000; ++j){void* pMemory = operator new(10000);operator delete(pMemory);}}end = clock();TRACE_FUCTION_AND_LINE("operator new takes %.2f seconds", (end-start) / CLOCKS_PER_SEC);start = clock();for(int i = 0; i < 500; ++i){for(int j = 0; j < 10000; ++j){void* pMemory = new char[10000];delete [](pMemory);}}end = clock();TRACE_FUCTION_AND_LINE("new char takes %.2f seconds", (end-start) / CLOCKS_PER_SEC);start = clock();for(int i = 0; i < 500; ++i){for(int j = 0; j < 10000; ++j){void* pMemory = malloc(10000);free(pMemory);}}end = clock();TRACE_FUCTION_AND_LINE("malloc takes %.2f seconds", (end-start) / CLOCKS_PER_SEC);TRACE_FUCTION_AND_LINE("\n\n\n");}*/return 0;}


原创粉丝点击