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("
");
        printf("%02x ", *((uint8_t *)ptr + i));
    }
    printf("
");
}

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;
}
原文地址:https://www.cnblogs.com/Alexkk/p/15036471.html