c++ 对象大小内存占用分析
由于是64位机器,因此以下分析中指针都是占用64位
#include<bits/stdc++.h>
using namespace std;
// 1 空类对象
// sizeof emptyObj=1
class emptyClass{};
// 2 普通成员函数对象
// sizeof generalObj = 1
class hasGeneralFuntionClass{
public:
void show(){ cout<<" show()"<<endl;}
};
// 3 虚函数对象: 虚指针占用对象的内存空间
// sizeof virtualObj = 8
class hasVirtualFunctionClass{
public:
virtual void show(){cout<<"show()"<<endl;}
};
// 4 结构体对象
// 结构体对齐三条原则
// 1 首个成员从地址0开始
// 2 每个成员的首地址是自身大小的整数倍,不满足的地址需要填充,
// 即:如果当前成员大小为m字节,一定以m的倍数开始的地址存放该成员。
// 3 结构体整体补齐。
// 即:如果结构体最大成员是n字节,则最后的结构体大小一定是n的倍数,不满足的填充。
// 结构体成员放置原则:按序存放,参考测试3,4
// 测试1:原则1,原则2
// 11 00 00 00 22 22 22 22 33 33 00 00 00 00 00 00
// 44 44 44 44 44 44 44 44 55 55 55 55 00 00 00 00
// sizeof(AA)==32
struct AA{
char a; // 0x61fdd0 11
int b; // 0x61fdd4 22
short c; // 0x61fdd8 33
double d; // 0x61fde0 44
float e; // 0x61fde8 55
};
// 测试2:原则3
// 11 00 00 00 22 22 22 22 33 33 00 00
// sizeof(BB)==12
struct BB{
char a; // 0x61fdd0 11
int b; // 0x61fdd4 22
short c; // 0x61fdd8 33
};
// 测试3: 从小到大依次放成员
// 11 00 22 22 33 33 33 33 44 44 44 44 00 00 00 00
// 55 55 55 55 55 55 55 55
// sizeof(AA1)==24
struct AA1{
char a; // 0x61fdc0 11
short b; // 0x61fdc2 22
int c; // 0x61fdc4 33
float d; // 0x61fde8 44
double e; // 0x61fde0 55
};
// 测试4: 从大到小依次放成员
// 11 11 11 11 11 11 11 11 22 22 22 22 33 33 33 33
// 44 44 55 00 00 00 00 00
// sizeof(AA2)==24
struct AA2{
double a; // 0x61fde0 55
float b; // 0x61fde8 44
int c; // 0x61fdc4 33
short d; // 0x61fdc2 22
char e; // 0x61fdc0 11
};
void memory_dump(void *ptr, int len) {
int i;
for (i = 0; i < len; i++) {
if (i % 8 == 0 && i != 0)
printf(" ");
if (i % 16 == 0 && i != 0)
printf("\n");
printf("%02x ", *((uint8_t *)ptr + i));
}
printf("\n");
}
void printMemoryInfo(struct AA2 structObj){
memset(&structObj,0x00,sizeof(structObj));
memset(&structObj.a,0x11,sizeof(structObj.a));
memset(&structObj.b,0x22,sizeof(structObj.b));
memset(&structObj.c,0x33,sizeof(structObj.c));
memset(&structObj.d,0x44,sizeof(structObj.d));
memset(&structObj.e,0x55,sizeof(structObj.e));
memory_dump(&structObj,sizeof(structObj));
cout<<"a:"<<&structObj<<endl;
cout<<"b:"<<&structObj.b<<endl;
cout<<"c:"<<&structObj.c<<endl;
cout<<"d:"<<&structObj.d<<endl;
cout<<"e:"<<&structObj.e<<endl;
cout<<sizeof(structObj)<<endl;
}
void printMemoryInfo1(struct BB structObj){
memset(&structObj,0x00,sizeof(structObj));
memset(&structObj.a,0x11,sizeof(structObj.a));
memset(&structObj.b,0x22,sizeof(structObj.b));
memset(&structObj.c,0x33,sizeof(structObj.c));
memory_dump(&structObj,sizeof(structObj));
cout<<"a:"<<&structObj<<endl;
cout<<"b:"<<&structObj.b<<endl;
cout<<"c:"<<&structObj.c<<endl;
cout<<sizeof(structObj)<<endl;
}
// 5 vector 对象
// sizeof vectorObj=24, 因为有三个指针
// iterator start // 当前空间的头
// iterator end // 当前空间的尾
// iterator end_of_storage // 空用空间的尾
vector<int> vectorObj;
// 6 list对象
// sizeof listObj=24, 因为有2个指针+一个size_t
// _List_node_base *_M_next; // 前指针
// _List_node_base *_M_prev; // 后指针
// std::size_t _M_size; // 节点个数
list<int> listObj;
// 7 forwardlist 对象
// sizeof forwardListObj= 8 : 仅有一个next指针
forward_list<int> forwardListObj;
// 8 deque 对象
// sizeof deque = 80 :(4+4+2)*8=80
// 2
// _Map_pointer _M_map; 指向map:记录元素存放的桶位置
// size_t _M_map_size; map的大小:桶的个数
// ( 指向下面四个_M_cur,_M_first,_M_last,_M_node
// iterator _M_start; 第一个节点的位置:
// iterator _M_finish; 最后一个节点的下一个位置:
// )
// 4
// _Elt_pointer _M_cur;
// _Elt_pointer _M_first;
// _Elt_pointer _M_last;
// _Map_pointer _M_node;
deque<int> dequeObj;
// 9 stack 对象
// sizeof stackObj = 80, 基于deque实现,因此是dequeue的大小
stack<int> stackObj;
// 10 queue 对象
// sizeof queueObj = 80, 基于deque实现,因此是dequeue的大小
queue<int> queueObj;
// 11 rb_tree 对象
// sizeof rbTreeObj = 48
// _Rb_tree_color _M_color; 枚举bool值《-》需要对齐
// _Base_ptr _M_parent; 指向父节点的指针
// _Base_ptr _M_left; 指向左孩子的指针
// _Base_ptr _M_right; 指向右孩子的指针
// size_t _M_node_count 节点数量
// __gnu_cxx::__aligned_membuf<_Val> _M_storage 存放数据的指针
_Rb_tree<int, int, int,std::less<int>> rbTreeObj;
// 12 map 对象
// sizeof mapObj = 48 map和set的底层数据结构就是红黑树,因此大小为48
map<int,int> iMap;
// 13 set 对象
// sizeof msetObj = 48 map和set的底层数据结构就是红黑树,因此大小为48
set<int> iSet;
// 14 hashtable <-这儿的分析还有待大佬修正,由于visiual studio 坏了,一时间分析看不到内存
// size of hashTableObj=56
// __bucket_type *_M_buckets = &_M_single_bucket;
// size_type _M_bucket_count = 1;
// __node_base _M_before_begin;-->*next,*cur,val空间指针
// size_type _M_element_count = 0;
// _RehashPolicy _M_rehash_policy;
// 15 unorderd_map、unorderd_set 对象
// sizeof uiMap = 56, 因为底层是依靠hashtable实现的
unordered_map<int,int> uiMap;
int main(){
// class size
emptyClass emptyObj;
hasGeneralFuntionClass generalObj;
hasVirtualFunctionClass virtualObj;
cout<<sizeof(emptyObj)<<endl;
cout<<sizeof(generalObj)<<endl;
cout<<sizeof(virtualObj)<<endl;
// base type size
cout<<sizeof(char)<<endl; // 1
cout<<sizeof(short)<<endl; // 2
cout<<sizeof(int)<<endl; // 4
cout<<sizeof(float)<<endl; // 4
cout<<sizeof(double)<<endl; // 8
cout<<"size_t:"<<sizeof(size_t)<<endl; // 8
// struct size
struct AA2 structDoubleObj;
struct BB structIntObj;
printMemoryInfo(structDoubleObj);
printMemoryInfo1(structIntObj);
// vector size
cout<<sizeof(vectorObj)<<endl;
// list size
cout<<sizeof(listObj)<<endl;
// forward_list
cout<<sizeof(forwardListObj)<<endl;
// deque size
cout<<sizeof(dequeObj)<<endl;
// stack size
cout<<sizeof(stackObj)<<endl;
// queue size
cout<<sizeof(queueObj)<<endl;
// rb_tree size
cout<<sizeof(rbTreeObj)<<endl;
memory_dump(&rbTreeObj,sizeof(rbTreeObj));
// map size
cout<<sizeof(iMap)<<endl;
// set size
cout<<sizeof(iSet)<<endl;
// hashtable size
// unorderd_map size
cout<<sizeof(uiMap)<<endl;
return 0;
}