C++-----深度探索C++对象模型-第四章-Function语意学(三)
1、虚拟继承中的虚函数机制过于复杂,只建议不要在一个虚基类中定义一个非静态数据成员。
2、对于成员函数的一个测试,测试函数的效能可以得到两个结果:1)inline函数有明显的提升,消除了额外的时间负担,优化版本的inline函数效率更高。2)每多一层继承虚函数执行的时间就有明显的增加,增加继承深度就增加了执行成本。
3、对一个非静态数据成员取地址得到的是该成员在类布局中的位置也就是偏移量(再加1),一般要将其绑定在一个对象上才可以存取绑定在对象上读地址则是其真正的地址。
对一个非静态成员函数取地址,如果这个函数不是虚函数得到的结果是它在内存中的地址,但是它也要绑定在一个对象身上才可以调用。
对一个静态成员变量或函数取地址得到的都是其在内存中的地址。
4、定义一个成员函数指针如下:
double (point::*pmf)()=&point::z;
使用一个成员函数指针如果不用于虚函数、多重继承、虚基类等情况,并不会比使用一个非成员函数指针的成本更高。但是如果用在虚函数上情况就会复杂。
5、指向虚函数的指针,虚函数机制仍然可以在使用指向成员函数指针的情况下运转,虽然虚函数的地址在编译期是未知的,所知道的是虚函数在虚函数表中的索引,也就是说对虚成员函数取地址所获得的是其索引值。
6、由上可知,一个指向成员函数的指针,需要既可以指向非虚函数也可以指向虚函数但是指向虚函数只能得到其索引值,而非虚函数得到的是其真实的地址。所以编译器定义的ptr要能够1)持有两种数值。2)使得该值区分索引值和真实的地址。
7、为了让指向成员函数的指针也能够支持多重继承和虚拟继承,有的编译器设计了一种结构体,里面的数据分别保存虚函数表中的索引,和非虚函数的地址。需要知道的是,不同的编译器有自己不同的风格。
8、函数指针的效率:多重继承和虚拟继承一样即使在编译器优化的条件下还会有一定的时间负担。
9、inline函数:将class内的成员存取函数声明为inline,我们可以保持直接存取meimber的高效率,也保持了函数的封装性。关键字inline是一种请求,如果请求被接受,编译器会用一个表达式合理的将这个函数展开。将函数展开之后所带来的执行成本比一般的函数调用以及返回机制多带来的成本要低。一般编译器会计算函数中的赋值、函数调用次数、虚函数调用次数等等每种类型会有一个对应的权值,而inline函数的复杂度以这些权值的总和来决定。
10、处理inline函数有两个阶段:
1)分析函数定义,以决定是否能转化成inline函数,如果不行会转化成static函数,并且在被编译模块内产生对应的函数定义。
2)真正的inline函数扩展操作是在调用的那一点上,这会带来参数的求职操作和临时性对象管理。
11、在inline扩展期间:每一个形式参数都被对应的实际参数取代。如果实际参数是一个常量表达式,可以在替换之前完成求值操作。后继的inline替换就可以直接把常量绑上去,如果既不是一个常量表达式也不是一个带有副作用的表达式那么就直接替换。
12、inline函数中每一个局部变量都被放在函数调用的一个封闭区段,拥有独一无二的名称,如果inline函数以单一表达式扩展多次,则每次扩展都需要自己的一组局部变量。如果inline函数以分离的形式多个式子扩展多次,那么只需要一组局部变量,就可以重复使用。
13、inline函数对于封装提供了一种必要的支持,可以有效的存取封装与类中的非公有成员数据,可以将其看做C程序中宏定义的一个安全替代品,但是如果一个inline函数被调用太多次的话就会产生大量的扩展码,使程序大小暴增。、
14、inline参数带有副作用,或以一个单一表达式进行多次调用,或者inline中有多个局部变量都会产生临时对象。另外inline中如果再有inline会导致复杂度太高无法展开。这种情况可能出现在多重继承的构造函数。

浙公网安备 33010602011771号