标签:
Point3d obj; Point3d *ptr = &obj;当这样做:
obj.normalize(); ptr->normalize();时,会发生什么事情呢?其中的Point3d::normalize()定义如下:
Point3d Point3d::normalize() const { register float mag = magnitude(); Point3d normal; normal._x = _x / mag; normal._y = _y / mag; normal._z = _z / mag; return normal; }而其中的Point3d::magnitude()定义如下:
float Point3d::magnitude() const { return sqrt(_x * _x + _y * _y + _z * _z); }答案是:不知道.
float magnitude3d(const Point3d *_this) { ...} float Point3d::magnitude3d() const { ... }那么选择member function不应该带来什么额外负担,这是因为编译器内部已将"member函数实体"转换为对等的"nonmember函数实体".
float magnitude3d(const Point3d *_this) { return sqrt(_this->_x * _this->_x + _this->_y * _this->_y + _this->_z * _this->_z); }乍看之下似乎nonmember function比较没有效率,它间接地经由参数取用坐标成员,而member function确实直接取用坐标成员,然而实际上member function被内化为nonmember的形式,下面就是转化步骤:
// non-const nonstatic member的扩张过程 Point3d Point3d::magnitude(Point3d *const this)如果member function是const,则变成:
// const nonstatic member的扩张过程 Point3d Point3d::magnitude(const Point3d *const this)2.将每一个"对 nonstatic data member的存取操作"改为经由 this 指针来存取:
{ return sqrt(this->_x * this->_x + this->_y * this->_y + this->_z * this->_z; }3.将member function重新写成一个外部函数,对函数名称进行"mangling"处理,使它在程序中成为独一无二的语汇:
extern magnitude__7Point3dFV(register Point3d *const this);现在这个函数已经被转换好了,而其每一个调用操作也必须转换.于是:
obj.magnitude();变成了:
magnitude__7Point3dFV(&obj);而
ptr->magnitude();变成了:
// 以下描述"named return value函数"的内部转化 // 使用C++伪代码 void normalize_7Point3dFV(register const Point3d *const this, Point3d &__result) { register float mag = this->magnitude(); // default constructor __result.Point3d::Point3d(); __result._x = this->x / mag; __result._y = this->y / mag; __result._z = this->z / mag; return ; }一个比较有效率的做法是直接建构"normal"值,像这样:
Point3d Point3d::normalize() const { register float mag = magnitude(); return Point3d(_x / mag, _y / mag, _z / mag); }它会被转化为以下的代码:
// 以下描述内部转化 // 使用C++伪码 void normalize_7Point3dFV(register const Point3d *const this, Point3d &__result) { register float mag = this->magnitude(); // __result用以取代返回值(return value) __result.Point3d::Point3d(this->_x / mag, this->_y / mag, this->_z / mag); return ; }这可以节省default constructor初始化锁引起的额外负担.
class Bar { public: int ival; };其中ival有可能变成这样:
// member经过name-mangling之后的可能结果之一 ival_3Bar为什么编译器要这样做?请考虑这样的派生操作(derivation):
class Foo : public Bar { public: int iva; };记住,Foo对象内部结合了base class 和derived class 两者:
// C++伪码 // Foo的内部描述 class Foo { public: int ival_3Bar; int ival_3Foo; };不管要处理哪一个ival,通过"name mangling",都可以绝对清楚地指出来,由于member functions可以被重载化(overloaded),所以需要更广泛的mangling手法,以提供绝对独一无二的名称,如果把:
class Point { public: void x(float newX); float x(); };转换为:
class Point { public: void x_5Point(float newX); float x_5Point(); };会导致两个被重载化(overloaded)的函数实体拥有相同的名称,为了让它们独一无二,唯有再加上它们的参数链表(可以从函数原型中参考得到).如果把参数类型也编码进去,就一定可以制造逐独一无二的结果,使两个x()函数有良好的转换:
class Point { public: void x_5PointFf(float newX); float x_5PointFv(); }以上所示的只是cfront采用的编码方法,必须承认,目前的编译器并没有统一的编码方法.
void print(const Point3d &) { ... }但意外地被这样声明和调用:
// 以为是const Point3d & void print(const Point3d);两个实体如果拥有独一无二的name mangling,那么任何不正确的调用操作在链接时期就因无法决议(resolved)而失败.有时候可以乐观地称此为"确保类型安全的链接行为"(type-safe linkage)."乐观地"是因为它只可以捕捉函数的标记(signature,即函数名称+参数数目+参数类型)错误;如果"返回类型"声明错误,就没有办法检查出来.
ptr->normalize();将会被内部转化为:
(*ptr->vptr[1])(ptr);其中:
// register float mag = magnitude(); register float mag = (*this->vptr[2])(this);此时,由于Point3d::magnitude()是在Point3d::normalize()中被调用,而后者已经由虚拟机机制而决议(resolved)妥当,所以明确地调用"Point3d实体"会比较有效率,并因此压制由于虚拟机制而产生的不必要的重复调用操作:
// 明确的调用操作(explicity invocation)会压制虚拟机制 register float mag = Point3d::magnitude();如果magnitude()声明为 inline 函数会更有效率,使用 class scope operator明确调用一个 virtual function,其决议(resolved)方式会和nonstatic member function一样:
register float mag = magnitude_7Point3dFv(this);对于以下调用:
// Point3d obj; obj.normalize();如果编译器把它转换为:
(* obj.vptr[1])(&obj);虽然语意正确,却没有必要.请回忆那些并不支持多态(polymorphism)的对象(1.3节),所以上述经由obj调用的函数实体只可以是Point3d::normalize()."经由一个class object调用一个virtual function".这种操作应该总是被编译器像对待一般的nonstatic member function一样加以决议(resolved):
normalize_7PointdFv(&obj);这样优化工程的另一利益是,virtual function的一个 inline 函数实体可以被扩张(expanded)开了,因而提供极大的效益利益.
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/yiranant/article/details/47361385