我今天正在研究一些blitting代码,在分析后发现我创建了1000个新的矩形。我感到震惊,因为我只有1或2个不同的新Rectangle()调用,或者我正在使用BitmapData的.rect属性。
我开始评论大量的代码,直到我在sprite类中留下这段代码:
canvas.bitmapData.copyPixels(_bitmapData, _bitmapData.rect, destination, null, null, true);
我在创建对象时缓存了_bitmapData.rect的结果,并且我的数千个新的矩形调用突然从探查器中消失了。
为什么BitmapData.rect会创建一个新的矩形?有没有办法检查核心库或其他东西并确认这是真的?这似乎令人费解。
答案 0 :(得分:1)
为什么BitmapData.rect会创建一个新的矩形?有没有办法检查核心库或其他东西并确认这是真的?这似乎令人费解。
想象一下以下假设情况:BitmapData.rect
总是返回相同的Rectangle实例:
public function BitmapDataRectTest()
{
var bmp:BitmapData = new BitmapData(100, 100, true, 0);
var rect1:Rectangle = bmp.rect;
rect1.width = 200;
var rect2:Rectangle = bmp.rect;
trace(rect2.width); // 200 <--- this would be wrong,
// the BitmapData is still only 100 pixels wide.
}
BitmapData.rect
每次都会返回一个新实例,以避免出现这种情况,并确保在返回的Rectangle
实例中获取正确的数据。
最后注意事项:这涉及'按值传递'(基本类型)和'传递引用'(复杂类型)变量。有关详情,请查看有关stackoverflow的Google或其他帖子:Pass by reference or pass by value?
答案 1 :(得分:0)
是的,BitmapData.rect显然是一个在访问时创建新矩形的getter。
您可以通过比较参考或检查内存地址来证明:
示例:
package
{
import flash.display.Sprite;
import flash.display.BitmapData;
import flash.geom.Rectangle;
public class BitmapDataRectTest extends Sprite
{
public function BitmapDataRectTest()
{
var bmp:BitmapData = new BitmapData(100, 100, true, 0);
trace(bmp.rect == bmp.rect); // false
var rect1:Rectangle = bmp.rect;
var rect2:Rectangle = bmp.rect;
trace("Place breakpoint here and look at rect1 and rect2 memory addresses");
// rect1 address on my pc: @6900f71
// rect2 address on my pc: @6900f41
}
}
}
编辑本机类中的类似行为:
DisplayObject.transform
:在每次访问时返回新的Transform实例Transform.colorTransform
:在每次访问时返回新的ColorTransform实例DisplayObject.filters
:在每次访问时返回新的Array实例在所有这些案例中,课程保护自己免受破坏。只需这样考虑:当一个类使用聚合时,它不能按原样公开它的聚合实例,因为否则有必要在内部对象发生时通知主类的更改。这是更新和验证每个聚合实例的每个字段中的更改的大量逻辑。
答案 2 :(得分:0)
有趣的观察。
您可以使用===
运算符检查任何Object
的两个实例是否相同。
BitmapData
内部可能使用不同的数据结构来维持其可视状态。必须将rect
属性实现为getter函数。但是,人们会期望因为BitmapData
的维度是不可变的,所以Rectangle
对象永远不需要重新创建,甚至根本不需要重新计算。
修改 rect
上的BitmapData
属性为只读(无设置器),但Rectangle
上的属性不是。创建Rectangle
的新实例可确保外部对象无法进行突变。
答案 3 :(得分:0)
是的,这听起来很令人沮丧,但如果你看一下BitmapData类的源代码,你会发现这个:
public class BitmapData extends Object implements IBitmapDrawable {
...
public function get rect() : Rectangle {
return new Rectangle(0, 0, this.width, this.height);
}
...
}
所以答案是肯定的,每次通过访问器函数检索时,AVM都会在堆中创建新的Rectangle实例。