常规new和布局new
来源:互联网 发布:在淘宝上开网店程序 编辑:程序博客网 时间:2024/05/01 17:23
通常,new负责在堆(heap)中找到一个能够满足要求的内存块,new操作符还有另外一种变体,称为布局(placement)new操作符,它能够让你指定要使用的位置。
要使用布局new,首先要包含头文件new,它后面需要一个提供地址的参数。话不多说看代码。
// newplace.cpp -- using placement new#include <iostream>#include <new> // for placement newconst int BUF = 512;const int N = 5;char buffer[BUF]; // chunk of memoryint main( ){ using namespace std; double *pd1 , *pd2; int i; cout << "Calling new and placement new:\n"; pd1 = new double[N]; // use heap pd2 = new ( buffer ) double[N]; // use buffer array for( i = 0; i < N; i++ ) pd2[i] = pd1[i] = 1000 + 20.0 * i; cout << "Memory addresses:\n" << " heap: " << pd1 //常规new在堆上分配内存的首地址 << " static: " << ( void * ) buffer << endl; //布局new在buffer上分配的首地址 cout << "Memory contents:\n"; for( i = 0; i < N; i++ ) { cout << pd1[i] << " at " << &pd1[i] << "; "; cout << pd2[i] << " at " << &pd2[i] << endl; } cout << "\nCalling new and placement new a second time:\n"; double *pd3 , *pd4; pd3 = new double[N]; // find new address pd4 = new ( buffer ) double[N]; // overwrite old data for( i = 0; i < N; i++ ) pd4[i] = pd3[i] = 1000 + 40.0 * i; cout << "Memory contents:\n"; for( i = 0; i < N; i++ ) { cout << pd3[i] << " at " << &pd3[i] << "; "; cout << pd4[i] << " at " << &pd4[i] << endl; } cout << "\nCalling new and placement new a third time:\n"; delete[] pd1; pd1 = new double[N]; pd2 = new ( buffer + N * sizeof( double ) ) double[N]; for( i = 0; i < N; i++ ) pd2[i] = pd1[i] = 1000 + 60.0 * i; cout << "Memory contents:\n"; for( i = 0; i < N; i++ ) { cout << pd1[i] << " at " << &pd1[i] << "; "; cout << pd2[i] << " at " << &pd2[i] << endl; } delete[] pd1; delete[] pd3; // cin.get(); return 0;}
下面是程序的输出(不同电脑运行结果可能不同)
我们可以看到
1:布局new确实将p2放在了buffer中,p1则是放在堆中
2:在第二次操作时,常规new查找的是一块新的内存块,布局new分配和以前相同的内存,说明布局new只传递地址,并不跟踪该内存块是否使用过,也不查找未使用的内存块,内存管理的负担交给程序猿
3:是否使用delete来释放内存——对于常规new,delete [ ] pd1;释放最初申请的内存,接下来再次调用new时该内存块可用,程序并没有使用delete来释放布局new分配的内存,这个例子中不能这么做。buffer是静态内存,delete只能用于常规new分配的堆内存,数组buffer位于delete的管辖区之外。当然,如果buffer是用常规new来创建的,也可以用delete释放。
将布局new用于类对象时,情况更复杂。话不多说,先上代码。
#include <iostream>#include <string>#include <new>using namespace std;const int BUF = 512;class JustTesting{private: string words; int number;public: JustTesting( const string & s = "Just Testing" , int n = 0 ) { words = s; number = n; cout << words << " constructed\n"; } ~JustTesting( ) { cout << words << " destroyed\n"; } void Show( ) const { cout << words << ", " << number << endl; }};int main( ){ char * buffer = new char[BUF]; // get a block of memory JustTesting *pc1 , *pc2; pc1 = new ( buffer ) JustTesting; // place object in buffer pc2 = new JustTesting( "Heap1" , 20 ); // place object on heap cout << "Memory block addresses:\n" << "buffer: " << ( void * ) buffer << " heap: " << pc2 << endl; cout << "Memory contents:\n"; cout << pc1 << ": "; pc1->Show( ); cout << pc2 << ": "; pc2->Show( ); JustTesting *pc3 , *pc4; // fix placement new location pc3 = new ( buffer + sizeof( JustTesting ) ) //非优化版pc3 = new (buffer) JustTesting("Bad Idea", 6); JustTesting( "Better Idea" , 6 ); pc4 = new JustTesting( "Heap2" , 10 ); cout << "Memory contents:\n"; cout << pc3 << ": "; pc3->Show( ); cout << pc4 << ": "; pc4->Show( ); delete pc2; // free Heap1 delete pc4; // free Heap2 // explicitly destroy placement new objects pc3->~JustTesting( ); // destroy object pointed to by pc3 非优化版无此行 pc1->~JustTesting( ); // destroy object pointed to by pc1 非优化版无此行 delete[] buffer; // free buffer // std::cin.get(); return 0;}
非优化版本的运行结果如图所示:
优化版本运行结果如下入所示:
对运行结果的差异做出几点说明:
1:程序员想用布局new创建多个对象时,必须提供两个不同的缓冲区地址,否则新对象会覆盖第一个对象的内存空间
2:使用布局new为对象分配内存时,必须确保析构函数被调用,但同时,我们又不能使用 delete pc1;这样的方式来做,因此必须显式地为使用布局new操作符创建的对象调用析构函数,我们删除的时候,应当以创建顺序相反的顺序进行删除,因此晚创建的对象可能依赖于早创建的对象。仅当所有对象都被销毁后,才能释放存储这些对象的缓冲区。
推荐一篇博文,讲得很好。
http://www.cnblogs.com/sunrunner/p/3716134.html
- 常规new和布局new
- 写operator new和operator delete时要遵循常规
- 条款51:编写new和delete时需固守常规
- 条款51:编写new和delete需固守常规
- 条款51:编写new和delete时需固守常规
- 编写new和delete时需固守常规
- 条款51:编写new和delete时需固守常规
- placement new 布局new操作
- new 和operator new
- 布局NEW操作符
- 布局new操作符
- new 、operator new 和 placement new 区别
- new,operate new和placement new
- new、operator new和placement new
- new,operate new和placement new
- new 、operator new 和 placement new 区别
- new operator /operator new 和placement new
- new 、operator new 和 placement new 区别
- Linux使用之一安装安装scim中文输入法
- Design Thinking | 创新设计流程的7个模式
- 【JavaWeb-18】ActionContext存取数据、ValueStack存取值、EL新查找顺序、iterator、OGNL投影、其他标签、UI主题、防重复提交
- Mobius函数计算 定义+代码模板
- 2016年9月英语学习总结
- 常规new和布局new
- 类模板1——基本概念
- Spring中@ModelAttribute注解用法小结
- HDU 1272 小希的迷宫 并查集判断回路和连通
- XPATH 注入的介绍与代码防御
- Win32 程序基础知识
- JSP页面输入汉字为乱码的解决办法
- H3C中批量端口添加到Vlan
- JQuery的Dom操作