读书人

placement new的有关问题

发布时间: 2012-03-30 17:32:10 作者: rapoo

placement new的问题
关于 placement new 的问题:
----------------
在网上找了很多关于placement new的介绍,有很多都是这样说的;

引用:
使用方法
第一步 缓存提前分配
class Task {/*..*/};
char * buff = new [sizeof(Task)]; //分配内存
第二步:对象的分配
Task *ptask = new(buff) Task
第三步:使用
ptask-> suspend();
第四步:对象的毁灭
ptask-> ~Task(); //调用外在的析构函数
第五步:释放
你可以反复利用缓存并给它分配一个新的对象(重复步骤2,3,4)如果你不打算再次使用这个缓存,你可以象这样释放它
delete [] buff;
跳过任何步骤就可能导致运行时间的崩溃,内存泄露,以及其它的意想不到的情况。如果你确实需要使用placement new,请认真遵循以上的步骤。


---------
问题:
1> 第一步改成这样行不行?
char *buff = operator new [sizeof(Task)] ;// 用operator 来分配空间,不作初始化
2> 还有一些参考资料上说placement new和内存对齐的关系比较大,如果使用不档,会造成大的问题。内存对齐我是知道的,但是请问会造成什么问题?(举个简单例子看看)应该怎么避免(或者解决)这样的问题??


[解决办法]
char * buff = new [sizeof(Task)]; //分配内存????????????????????
char * buff = new char[sizeof(Task)];这样吧

这个代码能编译过去么?
char *buff = operator new [sizeof(Task)] ;// 用operator 来分配空间,不作初始化


调整边界?不太懂这个
[解决办法]
高手都度假去了,就让我冒充一下高手,呵呵
(1)
可以,但你有个笔误: 应该是operator new (sizeof(Task)), 而不是operator new [sizeof(Task)]. 顺便说一句,用你的方法和直接用new char[sizeof(Task)]差不多,因为char没有构造函数,也就没有初始化代价, 之不过你用operator new()申请内存,而后者用的是operator new[]()

(2)
对齐概念你很清楚,我就不用多解释了.有些系统要求(不是编译器的要求,而是操作系统甚至硬件的要求)对象的起始地址要是某个数(例如8)的倍数.不符合这一要求可能会引起严重后果.我们一般写程序时无需多虑这一点,是因为编译器作了以下两件事情:
1. 栈上的对象(注意,是类对象,char类型就无需了,后面还会提到)保证放在对齐地址上.
2. 用malloc, operator new()等申请的堆内存的起始地址都已对齐.
因此不管是栈对象和new出来的堆对象,地址都是对齐的. So far so good, 但inplacment new带来一个微妙的问题. 设想一下下面的语句:
char buf[sizeof(T)];
T* ptr = new (buf) T();
因为buf是char数组,编译器没有义务把它放在对齐地址上,因此,接下来ptr所指的T对象可能有对齐问题!
通过这些分析我们就很明白了,防止placement new的对齐错很简单: 永远不要以栈地址来inplacement new, 而要先申请堆内存.
btw, 关于此问题Hutter的大作 < <Exceptional C++> > 上有很精彩的描述.请参看其中的Item 30: The "Fast Pimpl " Idiom



[解决办法]
deng2000() 说的不错

读书人网 >C++

热点推荐