我们都知道STL封装的std::set内部的各元素是使用红黑树(RBtree)来管理的,以进行对元素按照默认的或指定的排序方式进行排序。红黑树的原理就不做过多介绍了,本次主要分析一下set元素的内存分布。
以下分析基于64位操作系统。
typedef struct tagCell
{
int id;
void *ptr;
tagCell()
: id(-1)
, ptr(NULL)
{}
}Cell;
struct CMP {
bool operator()(Cell a, Cell b) const
{
return a.id < b.id;
}
};
int main ()
{
std::set<Cell, CMP> cellset;
for (int i = 0; i < 5; i++) {
Cell cell;
cell.id = i;
cellset.insert(cell);
}
std::set<Cell, CMP>::const_iterator it = cellset.begin();
for (; it != cellset.end(); ++it) {
printf("\t %d\n", it->id);
}
return 0;
}
通过查看set变量的大小得知,set变量占用48字节大小空间。
(gdb) p sizeof(cellset)
$1 = 48
查看变量的内存信息:
(gdb) x/6gx &cellset
0x7fffffffdef0: 0x0000000000602dd8 0x0000000000000000
0x7fffffffdf00: 0x0000000000604050 0x0000000000604010
0x7fffffffdf10: 0x0000000000604110 0x0000000000000005
按照64位的8字节对齐,每8字节是一个地址。
第三个:根节点地址
第四个:最左端的节点地址
第五个:最右端的节点地址
第六个:节点数量
每个元素占用32+sizeof(T)字节,以下查看根节点信息:
(gdb) x/6gx 0x0000000000604050
0x604050: 0x0000000000000001 0x00007fffffffdef8
0x604060: 0x0000000000604010 0x00000000006040d0
0x604070: 0x0001000000000001 0x00007fffffffdf20
第一个:红黑树标记:0,红;1,黑。
第二个:父节点地址
第三个:左子节点地址
第四个:右子节点地址
第五个之后:具体元素内容
展开后如下图: