C++中内存对齐与对象指针指向空指针的对象大小
首前看一段程序,判断一下其输出结果是什么:
#include <iostream>
#include <vector>
#include <algorithm>
#include <bitset>
using namespace std;
class A{
int a;
int b;
double c;
char name;
char name2;
public:
virtual void myFun(){
cout<<"test"<<endl;
}
void myFun2(){
cout<<"fun2"<<endl;
}
};
int main(){
A *a = NULL;
cout<< sizeof(a)<<" "<< sizeof(*a)<<endl;
a->myFun();
a->myFun2();
return 0;
}
在Windows10 64位系统下,使用MInGW(gcc)作为编译器的情况下,
输出:
当执行a的myFun()函数时程序出错退出.
将普通函数的调用注释掉:
int main(){
A *a = NULL;
cout<< sizeof(a)<<" "<< sizeof(*a)<<endl;
// a->myFun();
a->myFun2();
return 0;
}
输出:
可以看到程序是正常结束的。
分析:
因为对象a的虚函数表示空的,所以调用虚函数时程序退出;而在调用普通函数时,实际调用形式是:A::myFun2(this),this指向调用对象,这里的this对象是一个空对象,在进行与成员变量无关的操作的时候是可以正常进行的。
sizeof(a)得到的是一个指针的大小,为8字节;sizeof(*a)得到了一个对象的大小,但是这里要遵循字节对齐的规则,虚函数表指针:8,成员变量:4+4+8+1+1=18,总大小为8+18=26,但是大小应为最大成员变量的整数倍,所以为:32
下面再来看一下一个空对象的大小:
#include <iostream>
#include <vector>
#include <algorithm>
#include <bitset>
using namespace std;
class A{
// int a;
// int b;
// double c;
// char name;
// char name2;
public:
// virtual void myFun(){
// cout<<"test"<<endl;
// }
void myFun2(){
cout<<"fun2"<<endl;
}
};
int main(){
A *a = NULL;
cout<< sizeof(a)<<" "<< sizeof(*a)<<endl;
// a->myFun();
a->myFun2();
return 0;
}
输出结果为:
“To ensure that the addresses of two different objects will be different.”所以即使一个类不含任何成员,也要有一个字节来标示其身份。