C++ primer 修正和疑问。(8.4.5 定位New)

14 views
Skip to first unread message

邱戈川

unread,
Mar 8, 2006, 9:41:14 PM3/8/06
to 基于ACE和SpiderMonkey的SMS虚拟运营系统
对于定位New的解析,书中并没有说清楚,先补充如下:

对于定位New,是指预先分配一个空间,然后再在这个空间中分配对象。

特点:
在预定空间分配的对象和这个空间在同一个地址上。

注意点:
1、无论在这个空间生成多少个对象,其地址都一样,就是这个空间的地址。
2、书中说
// 检查一个对象是否被放在buf 中
if ( pb->val() == 0 )
我觉得这是不对,就算buf
只有一个空间,也能生成对象。所以只要生成了对象,这个判断都是真。

我认为应该是:
if(pb == buf)//???

这样对么?

3、对于生成的对象必须手动析构,不然将无法释放对应的(如在构造函数中生成了对象,但是如果没有调用析构函数则会内存泄露):
pb->~Foo();

这些书上并没有说明。

时代过客

unread,
Mar 12, 2006, 9:42:02 PM3/12/06
to 基于ACE和SpiderMonkey的SMS虚拟运营系统
// 检查一个对象是否被放在buf 中
if ( pb->val() == 0 )
=================================
这句没看明白.

这种空间申请与对象初始化分离的做法是很有用的.比如实现对象内存池时,就可以用到,可以先在堆里申请一大块的内存空间,这空间只是纯粹的空间,当使用时就提取出来分配给各个不同的对象,然后再由各个独立的对象再自行初始化就行了,回收时在各个类里得先自行显式地调用析构函数(如果是POD<plain
old
data>类型的空间就省去这一步,STL的内存池就是这样做的),再把空间还给内存池,这样子就可以达到空间的重用性

candid Qiu

unread,
Mar 12, 2006, 9:51:37 PM3/12/06
to ACE...@googlegroups.com
如何"使用时就提取出来分配给各个不同的对象"??
又如何"再把空间还给内存池"??

每次调用 new (buf) ...都是返回相同的内存地址,所以如何解析上面的问题?

时代过客

unread,
Mar 12, 2006, 10:32:42 PM3/12/06
to 基于ACE和SpiderMonkey的SMS虚拟运营系统
我简单说说STL的内存池实现吧.
STL把内存块分为16种大小,从8开始到128结束,之间以8字节对齐.假如说有两个类A和B,sizeof(A)=6,sizeof(B)=17,list<
A > aList,list< B >
bList,这两个容器都使用同一个内存池但不同大小的串列类别,aList使用的是8大小的内存块,bList使用的是24大小的内存块,当这两个容器有元素加入时,就会分别从8大小和24大小处各摘走一块内存到各自的实例类里使用,在使用前就会调用new
(buf)
...来初始化各自的类,当各自的实例弹出这块内存时,就会先调用各自的析构函数来释放自己的资源,最后将各自大小的内存块放回内存缓冲区中.假如这时有另一个类C,sizeof(C)=19,list<
C >
cList,这个cList每个元素同样使用24大小的内存块,也就是说和B一样使用同一大小的内存块,尽管这时是使用相同大小的内存块,但它们却能各自独立,比如说有24大小的内存块buf在B向内存池申请内存时内存池将它摘给B使用,当B使用时,buf所属对象是B的,若B使用完还给内存池,这时C向内存池申请内存时,内存池再将buf摘给C使用,这时buf所属的对象是C,所以这样的空间申请与对象初始化分离的做法,能很好地用在内存池上

candid Qiu

unread,
Mar 12, 2006, 10:47:16 PM3/12/06
to ACE...@googlegroups.com
这是否意味着使用了那块内存都需要自行记录下来,这样分配给下一个对象时
不至于重复?

也就是如:

A * pA = new (buf) A;

B* pB = new (buf + sizeof(A)) B;

这样理解对么?

不过如果这样,释放后再重新利用将比较复杂?

日常开发中有用到过么?

时代过客

unread,
Mar 12, 2006, 11:05:52 PM3/12/06
to 基于ACE和SpiderMonkey的SMS虚拟运营系统
空间不一定是连续的.很多时成是离散的,将内存块并存放在串列里(DDK里叫lookaside),在同一串列里其内存块大小是相同的.

当内存块从内存池摘走给一个客户端后,若再从内存池取相同大小的内存块时,内存池也就不会将前面已摘走的内存块给当前请求的客户端.当回收时,内存池只需简单地将相同大小的内存块放入在相同的串列就可以了,这样子就可以省去频繁向系统申请堆空间的开销,同时也能兼顾到各个不同类对内存空间的初始化

时代过客

unread,
Mar 12, 2006, 11:06:11 PM3/12/06
to 基于ACE和SpiderMonkey的SMS虚拟运营系统
空间不一定是连续的.很多时成是离散的,将内存块并存放在串列里(DDK里叫lookaside),在同一串列里其内存块大小是相同的.

当内存块从内存池摘走给一个客户端后,若再从内存池取相同大小的内存块时,内存池也就不会将前面已摘走的内存块给当前请求的客户端.当回收时,内存池只需简单地将相同大小的内存块放入在相同的串列就可以了,这样子就可以省去频繁向系统申请堆空间的开销,同时也能兼顾到各个不同类对内存空间的初始化

Reply all
Reply to author
Forward
0 new messages