欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

SGI STL中的union obj

程序员文章站 2022-05-19 16:09:39
...

这两天开始看侯捷的STL源码剖析,STL的allocator中的第二级配置器__default_alloc_template时,free-list的节点结构:

union obj
{
    union obj* free_list_link;
    char client_data[1];
};

书中对此的解释是是:

由于union之故,从其第一字段观之,obj可被视为一个指针,指向相同形式的另一个obj。从其第二字段观之,obj可被视为一个指针,指向实际区块

此处的char client_data[1]不太好理解,尤其是在allocate、refill、mempool中都没有用到这个字段。

个人感觉此处至少涉及了三个知识点:1,链表;2,union的共享内存;3,柔性数组;

加入为此节点申请一个8字节的空间:

obj * block = (obj *) malloc(8);
printf("%x\n", block);
printf("%x\n", block->client_data);

此处,block与block->client_data地址是一样的,从内存上来看,由于union的缘故很好理解:

SGI STL中的union obj

申请的八个字节,前四个字节可以用来存储一个指针free_list_link用于指向下一个obj内存块,或者头一个字节就是client_data[1],由于数组名即代表指针,那么client_data==block,都指向申请的8字节内存的首地址。

注意:以上特性在同一时刻只能取其一(也就是是否将内存返回给了客户端)

所以好多人说用一个结构体完全是可以实现(有人说已经尝试过注释掉没有问题,不知真假):

struct obj
{
    struct obj* free_list_link;
};

那么为什么作者一定要添加client_data呢?以下是我了解到的两个解释:

1,一种指针类型转换

一般内存buffer我们都是使用char*指针,如果要使用obj的地址,还得加上 (char *)block 进行强制类型转换。反之直接使用myBlock->client_data即可,方便多了。

2,构造包含柔性数组成员的节点,这样一个结构体可以占用任意大小的内存块

由于,二级配置器维护了16个free-list,每个free-list节点所占的内存是不一样的,已8的倍数递增,最大128字节。所以通过包含柔性数组,就可以将一个节点结构通用的满足不同size的结点。

 

以上两点的解释始终不能彻底的解决我心中的疑惑,就感觉实现上面的目的而添加client_data,根本就只是充分而非必要条件:

比如说第一点,用户根本不可能用联合体的成员访问自己申请的内存空间,都是直接使用节点的指针,从书上也能看出来,返回值为result,而result的类型就是obj*

在如第二点:obj*节点指针本身就是可以指向不同size的空间,为啥还非得用柔性数组成员呢?

https://blog.csdn.net/qq973177663/article/details/50815055?locationNum=9

中提到“设计者还是一种对精炼代码的极致追求吧”,如何追求的也不理解。。。

 

嗨,一知半解的往下看真的好难受啊!!!!

 

参考:

观点一:https://blog.csdn.net/w450468524/article/details/51649222

观点二:https://bbs.csdn.net/topics/340252517

柔性数组:

https://blog.csdn.net/vgxpm/article/details/42871601

http://www.cppblog.com/Dream5/articles/148386.html

其他:

https://segmentfault.com/q/1010000006209284/a-1020000006209968

https://bbs.csdn.net/topics/390408109

 

相关标签: STL源码剖析