标签:
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