漫谈析构函数(一)——从一个面试题开始

  • 时间:
  • 浏览:0

思考几分钟,看一下线程池池池输出:

  

1. 一有一两个 虚函数表(vtbl)会被编译器产生出来,结构存放Class的虚函数地址。(虚函数表是以Class维护的)

饱含一有一两个 虚函数的Class,以下3个操作会在编译期间发生:

(7) (Fun)*((int*)*(int*)(&b)+i)------------------------------最后你你你这人步将函数的地址转加上函数指针,完后 上端调用。

3. 对虚函数的调用会被改写,比如b.f(),f()为虚函数)会被改写成:(*b.vptr[1])(&b),其中1表示f()vtbl中的索引,&b代表调用f()this指针。(可非要看出虚函数的调用是都助于以间接调用完成,下行速率 相对普通成员函数要低)

(3) (Fun)*((int*)*(int*)(&b)+i)----------------------------得到vptr地址中存放的内容,即vptr(将会说vptr的值,将会说vtbl的地址)。

(2) 继承自base Class的那么被override的虚函数。

      (aClass A内存布局                           (bClass B 内存布局

说出下段代码的输出:

注:如图:有一两个 B的对象之间或有一两个 D的对象之间调用拷贝构造,“位逐次拷贝”无需发生难题,并且用D的对象给B的对象赋值(此时造成切割)就都助于调整vptrvirtual base Class偏移。

(4) (Fun)*((int*)*(int*)(&b)+i)----------------------------vtbl的地址转为int指针,为完后 与整型类型i相加做准备。

(5) (Fun)*((int*)*(int*)(&b)+i)---------------------------- 亲戚朋友知道指针与整数的相加,移动的是指针所指对象的大小,将会上一步将会转换为int型指针,并且会移动i*sizeof(int)个字节。

    将会你有难题,将会不理解,亲戚朋友就开彻底分析下你你你这人线程池池池。首先简单讨论一下虚函数在内存中与Class的关系。

注:虚函数在vtbl中的顺序和虚函数在Class中的声明顺序一致。

那么虚函数表中的“虚函数”都包括哪些呢?总共有以下三类:

(3) 纯虚函数(当前类定义的,将会从base Class继承来的)

cout<<sizeof(A)<<"  "<<sizeof(B)<<endl;(4,4)。

2. 每一有一两个 Class Object中,一有一两个 额外的虚函数表指针(vptr)会被编译器合成出来,内含vtbl的地址。vptr是以Class Object维护的)

综上,亲戚朋友可非要知道这句活假如有一天根据i的递增逐个调用B中的虚函数。B中的虚函数布局亲戚朋友将会知道,并且输出就比较慢理解了。

 

从上图可非要看出A,B的对象中那么数据成员,非要一有一两个 vptr,你你你这人亲戚朋友可非要输出验证:

注:通过你你你这人例子亲戚朋友还发现了一有一两个 难题,函数f()在基类A中是私有的,而亲戚朋友却访问到了。嘴笨 亲戚朋友将B中的h()声明为private,输出结果依然不变,从无需引起访问权限难题。也假如有一天说可非要外界访问到Class的私有虚函数。这是为哪些呢?其他人的理解是:访问限定符只在编译检查完后 起作用,而在线程池池池执行期间那么作用,将会从C++的函数名称修饰规则来看,并那么将访问限定符纳入其中,并且亲戚朋友假如有一天通过了编译,找到对应的函数地址就助于调用私有函数,将会在内存中私有函数和公有函数并没哪些区别。

(1) 被当前Class覆盖(override)的base Class中的虚函数

此外饱含一有一两个 虚函数的Class的默认合成构造函数以及拷贝构造函数不再是trivial,他都助于为每个Objectvptr设定初值,使其指向适当的vtbl

在开始英文英语 亲戚朋友的内容前,首先让亲戚朋友看一道面试题,题目如下:

(2) (Fun)*((int*)*(int*)(&b)+i)----------------------------vptr的地址强转成int型地址(指针),即让编译器将vptr的地址当做int型指针对待。并且*(&b)会被当做对象b

首先,由线程池池池中typedef句子亲戚朋友知道Fun是一有一两个 函数指针,也假如有一天这句话是要将某个地址转加上函数地址(指针)。具体步骤如下:

    说了那么多,亲戚朋友基本可非要推断出线程池池池中Class A,Class B的内存布局情形,如下图。注:Type_info完后 讨论,这里先忽略。

扩展:同理当一有一两个 Class直接或间接继承一有一两个 virtual base Class时,假如有一天再表现“位逐次拷贝语义”,默认构造函数和拷贝构造函数假如有一天再是trivial,将会都助于正确的设置virtual base Class的偏移。

(6) (Fun)*((int*)*(int*)(&b)+i)-----------------------------嘴笨 上一步假如有一天将指针移动到vtbl中相应表条目处(存放虚函数的地址),并且这里取出地址的内容假如有一天对应虚函数的地址。

    相信不少人对线程池池池中这条句子不是迷惑,下面亲戚朋友来逐步分析下这条句子的含义。

(1) (Fun)*((int*)*(int*)(&b)+i)----------------------------取对象b的地址,由对象的内存布局亲戚朋友知道对象b的地址和vptr的地址相同,即取vptr的地址。