sizeof不能用于计算STL容器中元素的数量

144 篇文章 6 订阅

 

接上文,我们知道在C++中sizeof计算map或者vector的大小的时候,无论容器里面有多少元素,返回的都是固定值,这个固定值就是C++中map或者vector这个数据结构本身所占用的空间。

对于vector来说,上文实测占用24字节,分成3个8字节的ptr,分别表示vector中首个元素的地址,下一个待插入的地址和后续扩展地址(当下一个地址达到后续扩展时,容器会自动再申请一段空间)。

对于map来说,上文实测占用48字节,但是具体着48字节表示什么,我们还灭有查到。本文再次进行分析:

#include <iostream>
#include <unistd.h>
#include <map>
#include <memory.h>
using namespace std;

int main(int argc, char** argv)
{
  std::map<std::string,int> smap;
  std::map<int,int> imap;
  unsigned long addr1[6]={0},addr2[6]={0};
  printf("smap addr= %p, sizeof(smap)=%d\n",&smap,sizeof(smap));
  for(int i =0; i<48; i++)
  {
    printf("%02X ",*(((unsigned char *)(&smap))+i));
  }
  printf("begin to insert content:\n");
  smap.insert(std::make_pair("123",1));
  for(int i =0; i<48; i++)
  {
    printf("%02X ",*(((unsigned char *)(&smap))+i));
  }
  printf("\n-------------\n");
  
  memcpy(addr1,&smap,48);
  
  smap.insert(std::make_pair("234",2));
  for(int i =0; i<48; i++)
  {
    printf("%02X ",*(((unsigned char *)(&smap))+i));
  }
  printf("\n-------------\n");
    memcpy(addr2,&smap,48);

  for(unsigned long i= addr1[4];i<addr2[4];i++)
  {
    printf("%02X ",*(unsigned char*)i);
  }
  printf("\n*************\n");
  
  printf("imap addr= %p, sizeof(imap)=%d\n",&imap, sizeof(imap));
  for(int i =0; i<48; i++)
  {
    printf("%02X ",*(((unsigned char *)(&imap))+i));
  }

  return 0;
}

 从一些资料分析的结果显示,std::map用的红黑树进行组织,这48个字节的后32个字节表示当前时刻map中的最后一个节点对应的红黑树结构,包括父节点地址,左节点地址,右节点地址,以及当前map中的元素数量。(前16个字节在map插入、删除过程中不变)

随着节点的插入与删除,红黑树的各节点会不断变化,在这个例子里,红黑树的一个节点大小为80字节(这个可能跟map的类型有关).这个80个字节里面包含了这个节点的父节点所在位置,这个节点的key的长度和内容,value的内容等信息。具体的,我还没有彻底看明白。比如下面*****之上打印的内容中,51 00 00 之前的01 00 00 00 00 00 00 00就是value,再往前的31 32 33 00 00 00 00 00 00表示key的内容,再往前的03 00 00 00 00 00 00 00 00表示key的长度;再往前8个字节表示key的所在位置,也就是0x5576EAAE32F0指向31 32 33所在位置,用于定位key。再往前的8个字节表示如果插入下一个节点,应该插入的位置。后面其他的,暂时不分析了。够用就行了。

 

 

#include <iostream>
#include <unistd.h>
#include <map>
#include <memory.h>
using namespace std;

int main(int argc, char** argv)
{
  std::map<std::string,int> smap;
  std::map<int,int> imap;
  unsigned long addr1[6]={0},addr2[6]={0};
  
  printf("smap addr= %p, sizeof(smap)=%d\n",&smap,sizeof(smap));
  for(int i =0; i<48; i++)
  {
    printf("%02X ",*(((unsigned char *)(&smap))+i));
  }
  
  printf("begin to insert content:\n");
  
  smap.insert(std::make_pair("123",1));
  for(int i =0; i<48; i++)
  {
    printf("%02X ",*(((unsigned char *)(&smap))+i));
  }
  printf("\n-------------\n");
  
  memcpy(addr1,&smap,48);
  
  smap.insert(std::make_pair("234",2));
  for(int i =0; i<48; i++)
  {
    printf("%02X ",*(((unsigned char *)(&smap))+i));
  }
  printf("\n-------------\n");
    memcpy(addr2,&smap,48);

  printf("addr1[4] = %p, addr2[4]=%p\n",addr1[4],addr2[4]);
  for(unsigned long i= addr1[4];i<addr2[4];i++)
  {
    printf("%02X ",*(unsigned char*)i);
  }
  
  printf("\n*************\n");
  
  smap.insert(std::make_pair("45678",4));
  for(int i =0; i<48; i++)
  {
    printf("%02X ",*(((unsigned char *)(&smap))+i));
  }
  printf("\n-------------\n");
    memcpy(addr1,&smap,48);

  for(unsigned long i= addr2[4];i<addr1[4];i++)
  {
    printf("%02X ",*(unsigned char*)i);
  }
  printf("\n*************\n");
  
  
  
  printf("imap addr= %p, sizeof(imap)=%d\n",&imap, sizeof(imap));
  for(int i =0; i<48; i++)
  {
    printf("%02X ",*(((unsigned char *)(&imap))+i));
  }

  return 0;
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值