深入了解sizeof计算规则

点击前往sizeof计算规则

union大小计算

系统及基本变量大小

系统

由于系统版本不一样,计算出来的大小会有差异。我的电脑系统如下:
在命令行中输入uname -a
root:xnu-8019.80.24~20/RELEASE_X86_64 x86_64
我的电脑是64位。

基本变量大小

#include <iostream>
#include <stdio.h>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;



int main()
{
    int a0[0], a1[1], a10[10];
    char *pc;
    int *pi;


    printf("size of char = %d\n", sizeof(char)); // 1
    printf("size of bool = %d\n", sizeof(bool)); // 1
    printf("size of short = %d\n", sizeof(short)); // 2
    printf("size of integer = %d\n", sizeof(int)); // 4
    printf("size of long = %d\n", sizeof(long)); // 由系统决定64位为8
    printf("size of long long = %d\n", sizeof(long long)); // 8

    // 数组大小 = 元素大小*个数 :: 0就是0个元素占用空间为0.
    // 数组在计算class内存时,可以认为定义了N个连续的变量。

    printf("size of a0 = %d\n", sizeof(a0)); // 0
    printf("size of a1 = %d\n", sizeof(a1)); // 4
    printf("size of a10 = %d\n", sizeof(a10)); // 40

    // 任何指针大小都为8字节
    printf("size of int pointer = %d\n", sizeof(pi)); // 8
    printf("size of char pointer = %d\n", sizeof(pc)); // 8

    return 0;
}
/*
代码输出
size of char = 1
size of bool = 1
size of short = 2
size of integer = 4
size of long = 8
size of long long = 8
size of a0 = 0
size of a1 = 4
size of a10 = 40
size of int pointer = 8
size of char pointer = 8
联合体union的大小取决于他所有成员中占用空间最大的一个成员的大小。
*/

class中内存占用规则

  1. 将所有元素用到的内存从上到下排列。(有一些隐藏的元素比如虚函数表指针)。
  2. 调整位置,将每个元素开始地址调整到自身大小的整数倍。
  3. 补齐,如果整个大小不是最大元素的整数倍则向后补齐达到整数倍。

多重继承情况(虚函数)

先对基类继承顺序从前到排序,基类里面排列规则是虚函数指针排第1,后面加上数据字段。最后放置本类内的元素。然后按照上述规则进行调整位置和补齐。最后补齐的标准是所有元素中最大值的整数倍。

实例分析

普通情况在上述链接中已经有举例,这里主要分析一下多重继承带虚函数的情况

虚函数

#include <iostream>
#include <stdio.h>
#include <vector>
#include <cmath>
#include <algorithm>

using namespace std;


class A {
    int a[0];
};

class B {
};

class C {
public:
    virtual void print1() {};
};

class D : public C {
public :
    void print1() {}

    short x;
};


class S {
public:
    S() { cout << "S()" << endl; }

    virtual ~S() { cout << "~S()" << endl; }

    static int a;
};

int main() {
    std::cout << sizeof(A) << std::endl; // 0
    std::cout << sizeof(B) << std::endl; // 1
    std::cout << sizeof(C) << std::endl; // 8
    std::cout << sizeof(D) << std::endl; // 16
    std::cout << sizeof(S) << std::endl; // 8
    return 0;
}

A中是一个长度为0的数组占用0.
B是一个空对象,底层实现占用1.
C对象中有一个虚函数指针占用8字节。
D有一外虚函数指针再接一个short, 最后对齐到8的倍数16.
S中static算一个全局变量,不能算在S的内存中,一个虚函数指针占用内存8.

多重继承



#include <iostream>
#include <stdio.h>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;

class D {
public:
    virtual void fund(){
    }
};

class A {
public:
    int b;
    virtual void funa(){
        cout<<"fa"<<endl;
    }
};


class E {
    short e;
};

class B:public A,D{
public:
    short a;
    void fund(){
        cout<<"fb"<<endl;
    }
};

class C:public D,A{
public:
    short a;
};


int main()
{
    cout<<sizeof(B)<<endl;
    cout<<sizeof(C)<<endl;
    return 0;
}

/*
32
24
*/

对于B排布如下

字段占用大小起始地址
vta80
b48
vtd816(上一行实际用到12,由于起始地址要等于自身的倍数,所以要从16开始)
a224

字段a结束地址是26,最终大小得最大字段(指针为8)的倍数,所以大小为32。

对于C排布如下

字段占用大小起始地址
vtd80
vta88
b416
a218

字段a结束地址是18,最终大小得最大字段(指针为8)的倍数,所以大小为24。


#include<iostream>
using namespace std;


class A
{
};

class B
{
    char ch;
    virtual void func0()  {  }
};

class C
{
    char ch1;
    char ch2;
    virtual void func()  {  }
    virtual void func1()  {  }
};

class D: public A, public C
{
    int d;
    virtual void func()  {  }
    virtual void func1()  {  }
};
class E: public B, public C
{
    long e;
    virtual void func0()  {  }
    virtual void func1()  {  }
};

int main(void)
{
    cout<<"B="<<sizeof(B)<<endl;    //result=16
    cout<<"C="<<sizeof(C)<<endl;    //result=16
    cout<<"D="<<sizeof(D)<<endl;    //result=16
    cout<<"E="<<sizeof(E)<<endl;    //result=32
    return 0;
}

/*
B=16
C=16
D=16
E=40
*/

虚继承

虚继承子类会产生自己的虚函数表指针。
父类没有成员数据时,不会产生新的指针表。


#include <iostream>
#include <stdio.h>
#include <vector>
#include <cmath>
#include <algorithm>

using namespace std;


class A {
public:
    virtual void print1() {};
};

class C {
public:
    int a;
    virtual void print1() {};
};

class D : virtual public C {
public :
    virtual void print1() {}
};


class E : public  C {
public :
    virtual void print1() {}
};


class F : virtual public A {
public :
    virtual void print1() {}
};

int main() {
    std::cout << sizeof(C) << std::endl; // 16 虚函数表+一个变量大小
    std::cout << sizeof(D) << std::endl; // 24 产生子类虚函数表
    std::cout << sizeof(E) << std::endl; // 16 非虚继承延用父类虚函数表
    std::cout << sizeof(F) << std::endl; // 8 父类无成员变量时不会产生新的虚函数表指针

    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值