关于STL中空间配置器中free

关于STL中空间配置器中free,第1张

freeList是一个元素类型为obj*的数组,freeList[i]代表着一串内存区块链表的首地址,每串区块的区块大小是不同的。假设freeList[0]代表一串区块大小为8的区块串,则它有可能是如下的形式

可以看出,在一个区块链表中,每两个obj加上后面没有颜色的一部分即为整个区块的大小

在这里聪明的你可能会问这样一个问题:为什么要用共用体,只用一个next指针不就完事了吗?

我认为是为了使得存储obj这块空间可以是char*类型的,避免在拿出一块时需要手动

地将obj部分的空间转成char*类型。

----------------------------------------------------------------------------------

至于区块链表是如何初始化的,可以看下面这段代码,链表的创建就在如下代码中的for循环部分。完整代码参考https://github.com/Alinshans/MyTinySTL/blob/master/MyTinySTL/alloc.h,需要注意原代码中有几处bug。

// 分配一个n个字节的区块,n已经被调整为8的整数倍
void* alloc::M_refill(size_t n)
	{
        
		size_t nblock = 10;
		// 获得nblock个区块
		char* c = M_chunk_alloc(n, nblock);
		FreeList* my_free_list;
		FreeList* result, *cur, *next;
		// 如果只有一个区块,就把这个区块返回给调用者,free list 没有增加新节点
		if (nblock == 1)
			return c;
		// 否则把一个区块给调用者,剩下的纳入 free list 作为新节点
		my_free_list = free_list[M_freelist_index(n)];
		result = (FreeList*)c;	// 将第一个区块返回
		free_list[M_freelist_index(n)] = my_free_list = next = (FreeList*)(c + n);	// 下一个区块的首地址,n >= 2
		for (size_t i = 1; ; ++i)
		{
			cur = next;		// 当前区块首地址
			next = (FreeList*)((char*)next + n);	// 下一个区块的首地址
			if (nblock - 1 == i)					// 目前的区块是第nblock个了
			{
				cur->next = nullptr;				// 当前区块没有下一个区块了
				break;
			}
			else
			{
				cur->next = next;
			}
		}
		return result;	// 返回一个可用的区块
	}

另外,free_list中相邻区块的首地址差的绝对值不一定是一个区块的大小,例如如下的情况:

    TinySTL::vector a(8);				// a拿到第一个区块
	TinySTL::vector b(8);				// b拿到第二个区块
	a.resize(128);							// 重新分配内存,并回收先前分配给a的区块
	TinySTL::alloc::showAddress();			// 打印一下free_list

输出结果:

 

 

计算一下第一个地址和第二个地址之间的差值

 2*16 - 1 * 16 = 16

 

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/1498891.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-25
下一篇 2022-06-25

发表评论

登录后才能评论

评论列表(0条)

保存