系统及基本变量大小
系统
由于系统版本不一样,计算出来的大小会有差异。我的电脑系统如下:
在命令行中输入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,后面加上数据字段。最后放置本类内的元素。然后按照上述规则进行调整位置和补齐。最后补齐的标准是所有元素中最大值的整数倍。
实例分析
普通情况在上述链接中已经有举例,这里主要分析一下多重继承带虚函数的情况
虚函数
#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排布如下
字段 | 占用大小 | 起始地址 |
---|---|---|
vta | 8 | 0 |
b | 4 | 8 |
vtd | 8 | 16(上一行实际用到12,由于起始地址要等于自身的倍数,所以要从16开始) |
a | 2 | 24 |
字段a结束地址是26,最终大小得最大字段(指针为8)的倍数,所以大小为32。
对于C排布如下
字段 | 占用大小 | 起始地址 |
---|---|---|
vtd | 8 | 0 |
vta | 8 | 8 |
b | 4 | 16 |
a | 2 | 18 |
字段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;
}
版权声明:本文为chenbb1989原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。