AS3 优化:隐式强制转换与 "as"参数和变量赋值;这到底是怎么回事?



已经表明(例如,AS3中的引用:强制转换或"as"),在AS3中使用"as"关键字比使用括号强制转换快3-4倍。这是因为(cast)可以更好地描述为插值,实际生成一个新对象,而不是真正地投射旧对象。(cast)如果失败,则抛出类型错误,其中"as"运算符返回null。好吧这里有三个问题:

(1) 当您将Number传递给期望(int)的函数时,或者当您将Sprite传递给期望DisplayObject的函数时会发生什么?即,如果函数期望父类。如果期望的类是作为参数传递的对象的上级,那么是否会生成一个新的、本地范围的对象?在调用函数之前,使用"as"强制转换参数是否明显更快?

(2) 例如,在将每个Sprite视为DisplayObject的for-each(someNumberVector中的vari:int)或for-each循环中发生了什么?在循环的每一步,每一个都是通过慢速(不是"as",而是容易出错的)方法重新铸造的吗?

(3) 就使用哪种方法(克隆或强制转换)来"强制转换"原始变量而言,函数或变量赋值需要一个接口实现类(或接口本身,例如IEventDispatcher)与使用父类相比有什么不同吗?

当您传递子类型的对象(或迭代子类型列表等)时,不需要强制转换或转换——对象是该子类型的,可以直接传递。原因是具有继承性的对象的内存布局通常被实现为基对象的数据,然后是下一个继承类的数据等,再加上一个vtable指针,以允许方法重写/接口实现:

// class Sub : Base
obj -> +----------+
       |vtable ptr| -.      vtable
       |----------|   `-> +---------+
       |Base data |       | Method1 |
       |----------|       +---------+
       |Sub data  |       | Method2 |
       +----------+       +---------+

当传递Sub对象时,底层指针指向内存中对象的起点——这与Base对象在内存中的起点完全相同,因此在内部从Sub转换为Base时无需执行任何操作;唯一的区别是如何使用变量(类型检查语义)。实际的对象值和对它的引用绝对不需要转换(无论如何,在一个合理的实现中)。

添加强制转换只会减慢速度(除非编译器足够聪明,可以删除强制转换,这是应该的,但我对AS3编译器的优化能力没有太多信心)。

然而,将Number s强制转换为int s,反之亦然,这是完全不同的,因为这需要转换值的内部表示形式,这很慢。

请注意对对象的引用(其中变量的实际值只是该对象的句柄)和值类型(其中变量实际值是值本身——没有间接性)之间的差异。例如,int变量保存实际的整数变量,而Object类型的变量仅保存对某个对象的引用。这意味着,如果您使用类型为Object的变量(或默认情况下为Object类型的非类型变量),并试图在其中粘贴一个整数,这将导致所谓的"装箱"操作,该操作获取值并将其粘贴到一个临时对象中,以便变量可以保留对它的引用,导致该装箱值被取消装箱,这显然不是即时的。

所以你可以看到,将对象强制转换到它们的基并不慢,因为没有工作要做。将基强制转换到派生类型几乎同样快(因为也不必对那里的内部指针执行任何操作),只是必须进行检查以确保对象真的是派生类型(根据执行的强制转换类型,会导致异常或null)。将值类型强制转换为对象类型(反之亦然)不是很快,因为除了运行时类型检查之外,还必须对值进行装箱/取消装箱。最后,将一种基本类型转换为另一种类型的速度特别慢,因为内部表示完全不同,并且相应地需要花费更多的精力来进行转换。

最新更新