sizeof 运算符
查询对象或类型的大小
在需要知道对象的实际大小时使用
语法:
- sizeof(类型)
- sizeof 表达式
解释
- 返回 类型 的对象表示的字节数。
- 返回当 表达式 求值时所返回的类型的对象表示的字节数。
#include <iostream>
class A
{
};
int main()
{
A a;
std::cout<< sizeof a <<endl; //OK 1
//std::cout<< sizeof A <<endl; //Error 可以是变量,但是不能是类型或者类,A是类
int Int1;
std::cout << sizeof Int1 << endl;
//std::cout << sizeof int << endl; //Error 可以是变量,但是不能是类型或者类,int是类型
std::cout << sizeof(float)<<endl; //OK 4,32编译器,float大小是4个字节
std::cout << sizeof(bool) <<endl;//OK 1,bool虽然只有一位,但是字节对齐,也是1一个字节
std::cout << sizeof(long) <<endl;//OK 4
std::cout << sizeof(long long) <<endl;//OK 8
return 0;
}
int i = 0;
A) sizeof(int); B)sizeof(i); C) sizeof i; D)sizeof int;
通过对比之后,除了D,其他都是正确的。所以如果可以的话,我们最好使用sizeof();
1.基本数据类型的sizeof
基本类型包括:bool ,char, short, int, long ,long long,float,double
32位编译器
指针都是4位
数据类型 | 大小 |
---|---|
bool | 1 |
char | 1 |
short | 2 |
int | 4 |
long | 4 |
long long | 8 |
float | 4 |
double | 8 |
64位编译器
指针都是8位
数据类型 | 大小 |
---|---|
bool | 1 |
char | 1 |
short | 2 |
int | 4 |
long | 8 |
long long | 8 |
float | 4 |
double | 8 |
2.结构体
结构体的sizeof涉及到字节对齐问题
注意:空结构体(不含数据成员)的sizeof值为1。这个和类是一样的。
struct A
{
char a;
int b;
};
sizeof(A); //值为8,字节对齐,在char之后会填充3个字节。
struct B
{
int b;
char a;
};
sizeof(B); //值为8,字节对齐,在char之后会填充3个字节。
struct C
{
};
sizeof(C); //值为1,空结构体也占内存
3.联合体
联合体是共享一段内存,其中最大的变量大小。
因为long long和double都是8个字节。
其中char str[21]本来最大内存是21个字节,但是是4字节对齐,所以需要补齐后面3个字节,所以大小是24字节
union u
{
bool b;
short s;
int i;
float f;
double d;
long l;
long long ll;
char str[21];
};
cout <<sizeof(u)<<endl; //值为24
4.数组大小
char str[]="abcd";//大小是5,因为后面还有一个'\0',所以要+1
char *pStr="abcd";//大小是4,32系统,这里pStr是指针
void funA(char a[5])
{
int len = sizeof(a);// len = 4,这函数里面,a不是数组类型,而是指针,所以大小是4
}
void funB(char a[])
{
int len = sizeof(a);// len = 4,这函数里面,a不是数组类型,而是指针,所以大小是4
}
5.指针
指针是用来记录另一个对象的地址,所以指针的内存大小当然就等于计算机内部地址总线的宽度。
在32位编译器中,一个指针变量的返回值必定是4。
指针变量的sizeof值与指针所指的对象没有任何关系。
char* str="123";
cout<<sizeof(str)<<endl;//4//这里是一个变量的大小
cout<<sizeof(*str)<<endl;//1,这里指的是一个char的大小
char *c[22];
cout<<sizeof(c)<<endl;//88,因为一个指针大小是4,22个指针就是88,所以大小是88
double *d;
cout<<sizeof(d)<<endl;//4,这里是指针的大小
cout<<sizeof(*d)<<endl;//8,这里是一个double变量的大小
long long **L;
cout<<sizeof(L)<<endl;//4,指针大小
cout<<sizeof(*L)<<endl;//4,指针大小
cout<<sizeof(**L)<<endl;//8,long long 大小
void (*pf)();//这是一个函数指针
cout<<sizeof(pf)<<endl;//4,指针大小
6.函数
int fun()
{
return 9;
}
double funD()
{
return 1.1;
}
void funV()
{
}
int test06()
{
cout<<sizeof(fun())<<endl; //4,相当于sizeof(int)
cout<<sizeof(int)<<endl;//4
cout<<sizeof(funD())<<endl; //8,相当于sizeof(double)
cout<<sizeof(double)<<endl;//8
cout<<sizeof(funV())<<endl;//1,相当于sizeof(void)
cout<<sizeof(void)<<endl;//1
void (*fv)();
fv = funV;
cout<<sizeof(fv)<<endl;//4,指针大小
double (*df)(double,double);
df = funD;
cout<<df(1.3,9.1)<<endl;//10.4
cout<<sizeof(df)<<endl;//4,指针大小
return 0;
}
7.类
注意不要说类的大小,是类的对象的大小.
首先,类的大小是什么?确切的说,类只是一个类型定义,它是没有大小可言的。 用sizeof运算符对一个类型名操作,得到的是具有该类型实体的大小。
如果 Class A; A obj; 那么sizeof(A)==sizeof(obj) 那么sizeof(A)的大小和成员的大小总和是什么关系呢,很简单,一个对象的大小大于等于所有非静态成员大小的总和。
空类
#include <iostream>
using namespace std;
class A
{
};
class B
{
public:
void fun(){}
B(){}
~B(){}
};
class C
{
public:
C(){}
virtual ~C(){}
virtual void fun(){}
};
int main()
{
cout<<sizeof(A)<<endl;//1,类的大小不为0,空类大小为1
cout<<sizeof(B)<<endl;//1,类中普通函数没有大小
cout<<sizeof(C)<<endl;//4,类C中包含虚函数,编译器会在给类中生成一个虚函数表,
//并在该类型的每一个实例中添加一个指向虚函数表的指针。
//在32位的机器上,一个指针占4个字节的空间,因此sizeof(C)是4,
//而且不论有多少个虚函数,都是一个指针大小
return 0;
}
struct S
{
char c;
};
class C
{
public:
C(){}
virtual ~C(){}
virtual void fun(){}
};
class D {
char ch;
void func() { }
};
class E {
char ch1; //占用1字节
char ch2; //占用1字节
virtual void func() { }
};
class E_2 {
char ch1; //占用1字节
int i1; //4
char ch2; //占用1字节
virtual void func() { }
};
class F {
float f;
virtual void func() { }
};
int test02()
{
cout<<sizeof(D)<<endl;//1
cout<<sizeof(E)<<endl;//8
cout<<sizeof(E_2)<<endl;//16
cout<<sizeof(F)<<endl;//8
cout<<sizeof(S)<<endl;//1
return 0;
}
这里我们发现,如果只有一个字节,那么就不用对齐什么的了,如果大小不是1,那么我们就要注意字节对齐,如类E,和类E_2,在两个char型之间,加了一个int型,就导致大小变成了16,因为第一个char型虽然只有1位,但是为了字节对齐,就变成了4字节,同样的是后面一个char型,也是一样,所以就变成了4+4+4+4 = 16.
求含有静态数据成员的类的大小
class T {
private:
int data = 2;
static char c;
};
cout<<sizeof(T)<<endl; //4
求继承类的大小
#include <iostream>
using namespace std;
class A {};
class B {};
class C {char c;};
class D {int c;};
class C_1{char c;};
class E:public A{};
class F:public A,public B,public C{};
class G:public A,public B,public D{};
class H:public C,public D,public C_1{};
class H_1:public C,public C_1,public D{};
class H_2:public C,public C_1,public D,public B,public A{};
int main()
{
cout<<sizeof(E)<<endl; //1
cout<<sizeof(F)<<endl; //1//继承一个或者多个空类,派生类还是空类,大小还是为1
cout<<sizeof(G)<<endl; //4
cout<<sizeof(H)<<endl; //12,按照父类的顺序来字节对齐,
cout<<sizeof(H_1)<<endl; //8,按照父类的顺序来字节对齐
cout<<sizeof(H_2)<<endl;//8,最后B,A两个父类是空类,但是H_2类前面几个父类不是空类,所以就大小还是8
return 0;
}
小结类的大小
1.为类的非静态成员数据的类型大小之和.
2.由编译器额外加入的成员变量的大小,用来支持语言的某些特性(如:指向虚函数的指针).
3.为了优化存取效率,进行的边缘调整(对齐).
4 与类中的构造函数,析构函数以及其他的成员函数无关.