C++中空类以及没有成员变量的类的大小&空对象指针调用成员函数

前言

最近在投简历参加面试,其中遇到了一些新的问题,搜索学习之后颇有所得,便想记录下心得。
这是乐游的笔试中出现的问题。

类的大小

首先来看一段代码
a和b是空类;

c继承a类,并且有虚函数;

d继承b和c类;


#include<iostream>
using namespace std;

class a{};

class b{};

class c :public a{
    virtual void fun() = 0;
};

class d :public b, public c{};

int main()
{

    cout << "sizeof(a)" << sizeof(a) << endl;

    cout << "sizeof(b)" << sizeof(b) << endl;

    cout << "sizeof(c)" << sizeof(c) << endl;

    cout << "sizeof(d)" << sizeof(d) << endl;

    return 0;

}

程序的结果是:

sizeof(a)=1

sizeof(b)=1

sizeof(c)=4

sizeof(d)=8

如何解释这个现象呢?
对于a和b这两个空类,本来应该是占0字节,但是输出为1。因为类是可实例化的(即使是空类),所以一个实例需要一个内存地址,如果空类占0字节,则在内存中不能够区分该实例,所以有一个隐含的字节占位。

对于c类,如果没有虚函数,它应该也是占1字节,但是有虚函数的情况下,不需要这个隐含的字节占位,并且有虚函数的类都有一个隐藏的虚函数指针,指向第一个虚函数的地址,这个指针占4字节,所以c占4字节。(函数都存放在代码区)

对于d类,它继承了b和c类,一个占1字节,一个占4字节,加起来却不是5字节,因为内存中数据对齐的原因,将1字节的b类对齐成了4字节,当然有3个字节是空的,这也形成了某种意义上的内存中的内部碎片(一般是指页式内存管理中的页不满的情况)。

空对象指针调用成员函数

先来看一段代码


#include<iostream>
#include<string.h>
using namespace std;
class A
{
public:
    static void f1(){ cout<<"f1"<<endl; }
    void f2()		{ cout<<"f2"<<endl; }
    void f3()		{ cout<<num<<endl; }
    virtual void f4() {cout<<"f4"<<endl; }
public:
    int num;
};
 
int main()
{
	A* pa = NULL;
	pa->f1();	//正常
	pa->f2();   //正常
	pa->f3();   //报错
	pa->f4();   //报错
    return 0;

程序的结果是:

f1正常;	

f2正常;

f3报错;

f4报错;

如何解释这个现象呢?
首先要了解c++中成员函数是怎么存储的。其实和普通函数一样,都是存放在代码区。在物理上两者并没有什么区别,只是在逻辑上成员函数是属于类的。

从这个角度来说,f1和f2能够正常运行便能够理解。

对于f3来说,它与f2的区别是调用了成员变量,由于此时只是并没有new一个对象出来,所以当调用成员变量时,编译器会自动调用this指针来找到当前对象的变量,而现在this未分配,所以会报错。

对于f4,是因为调用虚函数会先根据虚函数指针找到虚函数的地址再调用,而此时虚函数指针未分配,所以会报错。

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值