现在的位置: 首页 > 综合 > 正文

转:Inside the C++ Object Model学习笔记[Chap4.3-4.4]

2013年08月05日 ⁄ 综合 ⁄ 共 1897字 ⁄ 字号 评论关闭
 

4.3 指向成员函数的指针
取一个非静态数据成员的地址,得到的是该成员在类布局中的偏移量(未优化时还需要加1),它需要被绑定到某个类对象的地址上才可以存取;而取一个非静态成员函数的地址,若为非虚函数,那么得到的是在内存中的真正地址,但也需要被绑定到某个类对象的地址上,才能够通过它调用该函数,对于所有的非静态成员函数都需要对象的地址,即参数this指针。如果取一个虚函数地址,那么其在编译期间是未知的,所能知道的只是虚函数在其相关的vtbl中的索引值。
一个指向成员函数的指针声明语法为:
double ( Point::*pmf ) ();
定义并初始化该指针:
double ( Point::*coord ) () = &Point::x;
或者赋值操作:
coord = &Point::y;
调用方式如下:
( origin.*coord ) (); 或者 ( ptr->*coord ) ();
使用成员函数指针,如果不用于虚函数,多重继承与虚拟继承等情况,并不会比使用非成员函数指针的成本更高,但用于那三种情况时,其复杂度增加很多。
4.3.1指向虚拟成员函数的指针
指针调用虚函数所达到的多态行为,通过指向虚拟成员函数的指针也可以做到同样的效果,如:
class Point {
       public:
              virtual ~Point();
              float x();
              float y();
              virtual float z();
};
float ( Point::*pmf ) () = & Point::z;
Point *ptr = new Point3D;
通过pmf来调用z():
( ptr-.*pmf() );
其内部转换为(伪码):
( * ptr->vptr[ (int) pmf ]) ( ptr );
4.3.2【未】多重继承下指向成员函数的指针
 
4.3.3指向成员函数指针的效率
作者所作的测试条件:
1. 指向非成员函数的指针;
2. 指向类成员函数的指针;
3. 指向虚成员函数的指针;
4. 多重继承下的非虚以及虚拟成员函数指针;
5. 虚拟继承下的非虚以及虚拟成员函数指针。
4.4 内联函数
一般处理一个inline函数分为两个阶段:
1. 分析函数定义,以决定函数与编译器相关的内联能力:如果函数太复杂,或者因为建构问题(比如分配内存,取地址等操作),被判断为不可内联,那么它会被转换为一个static函数,并在被编译模块内产生对应的函数定义;
2. 真正的inline函数扩展操作是在调用的那一点上,这样会带来参数的求值操作以及临时性对象的管理等问题。
4.4.1形式参数
Inline函数在扩展期间,每一个形式参数都会被对应的实际参数取代,并且为了防止对实际参数的多次求值所引起的副作用,会引入临时性对象。如果实际参数时一个常量表达式,在替换之前先完成其求值操作,后继的内联替换,就可以把常量直接绑上去,如果既不是常量表达式,又不是带有副作用的表达式,那么就直接替换,如:
inline int min( int ival, int jval ) {
       return ival < jval ? ival : jval;
}
对其调用操作如下:
inline int bar() {
       int minval;
       int val1 = 1024;
       int val2 = 2048;
       minval = min( val1, val2 );         //--------
       minval = min( 1024, 2048 );        //--------
       minval = min( foo(), bar() + 1 );     //--------
       return minval;
}
标识①采用实际参数直接替换:minval = val1 < val2 ? val1 : val2;
标识②采用直接常量结果:minval = 1024;
标识③导入临时性对象避免重复求值:
int t1;
int t2;
minval = ( t1 = foo()), ( t2 = bar() + 1 ), t1 < t2 ? t1 : t2;
4.4.2局部变量
一般而言,inline函数中的每一个局部变量都必须被放在函数调用的一个封闭区段中,拥有一个独一无二的名称。如果inline函数以单一表达式扩展多次,那么每次扩展都需要自己的一组局部变量,如果inline函数以分离的多个式子被扩展多次,那么只需一组局部变量,就可以重复使用。
内联函数中的局部变量,再加上有副作用的参数,可能会导致大量临时性对象的产生。

说明:参数带有副作用,或是以一个单一表达式做多重调用,或是再inline函数中有多个局部变量,都会产生临时性对象

抱歉!评论已关闭.