您的位置:首页 > 编程语言 > C语言/C++

C++中关于sizeof使用的总结

2016-08-30 16:10 429 查看

一、内存字节对齐

参考

写出一个class,然后sizeof,sizeof的结果往往都比你声明的变量总长度要大,这是因为字节对齐。显然对齐更浪费了空间。那么为什么要使用对齐呢?对齐和不对齐,是在时间和空间上的一个权衡。对齐节省了时间。


1. 数据成员对齐规则:类中的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员大小(比如说是数组)的整数倍开始

2. 类作为成员:如果一个类中里有其他类成员,则其他类成员要从其内部最大元素大小的整数倍地址开始存储.(class A里存有class B,B里有char,int ,double等元素,那B应该从8的整数倍开始存储.)

3. 收尾工作:结构体的总大小,也就是sizeof的结果,.必须是其内部最大成员的整数倍.不足的要补齐.

class A
{
int i;//0.3
short s[5];//4.14
char c;//15.16 规则3
};
class B
{
char c0;//0.7
double d[3];//8.32  规则1
char c;//33.40 规则3
};


二、一个空类的sizeof的大小

class Test{

};


sizeof(Test)的结果是1.

因为一个空类也要实例化,所谓类的实例化就是在内存中分配一块地址,每个实例在内存中都有独一无二的地址。同样空类也会被实例化,所以编译器会给空类隐含的添加一个字节,这样空类实例化之后就有了独一无二的地址了。所以空类的sizeof为1。


三、不含成员变量,仅含构造函数和析构函数类的大小

class Test2{
Test2(){

}
~Test2(){

}
};


sizeof(Test2)的结果是1.

因为普通成员函数与sizeof无关。


四、不含成员变量,含虚析构函数

class Test3{
//long long i;
Test3(){

}
virtual ~Test3(){

}
};


sizeof(Test3)的结果是4.

因为虚函数放在虚表中,类中定义了虚函数,需要存放一个指向虚表的指针。指针占4个字节


五、测试

测试

#include<iostream>
using namespace std;
class A
{
public:
int a;
private:
char b;
};
class B
{
public:
static int a;
private:
char b;
};
class C
{
public:
int a;
virtual void f(){}
};
class D
{
public:
int a;
virtual void f(){}
virtual void f2(){}
virtual void f3(){}
};
//普通继承
class E
{
public:
int a;
private:
char b;
};
class F : public E
{
public:
int d;
char c;

};
class G
{
public:
int a;
private:
char b;
};
class H : public G
{
public:
char c;
int d;
};
//普通继承含虚函数的父类
class Test
{
public:
char a;
virtual void get(){}
};
class Test2 : public Test
{
public:
int a;
};
//含虚函数的子类普通继承含虚函数的父类
class Test3
{
public:
int a;
virtual void get(){}
};
class Test4: public Test3
{
public:
int a;
virtual void set(){}
};
//子类虚继承父类
class Test5
{
public:
int a;
};
class Test6 : virtual public Test5
{
public:
int b;
};
//子类和父类中都含虚函数的虚继承
//使用虚继承,子类和父类的虚函数存放在不同的虚表中,因此子类和父类都需要一个指向虚表的指针。
class Test7
{
public:
int a;
virtual void get(){}
};
class Test8 : virtual Test7
{
public:
int a;
virtual void set(){}
};
//多重继承
class Test9
{
public:
int a;
};
class Test10 : public Test9
{
public:
int b;
};
class Test11 : public Test9
{
public:
int c;
};
class Test12 : public Test10, public Test11
{
public:
int d;
};
//多重虚继承,由于是虚继承,虚基类数据成员a只需要保留一份。
class Test13
{
public:
int a;
};
class Test14 : virtual public Test13
{
public:
int b;
};
class Test15 : virtual public Test13
{
public:
int c;
};
class Test16 : public Test14, public Test15
{
public:
int d;
};

int   main()
{
cout << sizeof(A) << endl;//8
cout << sizeof(B) << endl;//1
cout << sizeof(C) << endl;//8
cout << sizeof(D) << endl;//8
cout << sizeof(E) << endl;//8
cout << sizeof(F) << endl;//16
cout << sizeof(G) << endl;//8
cout << sizeof(H) << endl;//16
cout << sizeof(Test) << endl;//8
cout << sizeof(Test2) << endl;//12
cout << sizeof(Test3) << endl;//8
cout << sizeof(Test4) << endl;//12
cout << sizeof(Test5) << endl;//4
cout << sizeof(Test6) << endl;//12
cout << sizeof(Test7) << endl;//8
cout << sizeof(Test8) << endl;//20
cout << sizeof(Test9) << endl;//4
cout << sizeof(Test10) << endl;//8
cout << sizeof(Test11) << endl;//8
cout << sizeof(Test12) << endl;//20
cout << sizeof(Test13) << endl;//4
cout << sizeof(Test14) << endl;//12
cout << sizeof(Test15) << endl;//12
cout << sizeof(Test16) << endl;//24

system("PAUSE");
}


六、普通继承总结

类的大小为类的非静态成员数据的类型大小之和,也就是说静态成员数据不作考虑。

普通成员函数与sizeof无关。

虚函数由于要维护在虚函数表,所以要占据一个指针大小,也就是4字节。

类的总大小也遵守类似class字节对齐的,调整规则。

七、虚继承

class   Parent
{
protected:
int   x;
public:
Parent(){ }
virtual   ~Parent(){}

};
class   Child:virtual   public   Parent
{
protected:
int   y;
public:
Child() :Top(){}
};


sizeof(Parent)的结果为8,sizeof(Child)的结果为16

因为虚继承,虚继承的子类都要包含一个指向基类的指针
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C++