2011-07-15 50 views
1

我正在研究一些blitting代碼,並在分析後發現我正在創建1000個新的矩形。我很震驚,因爲我只有1或2個不同的新的Rectangle()調用,或者我正在使用BitmapData的.rect屬性。BitmapData.rect創建一個新的矩形?

我開始註釋掉的代碼龐大的大片,直到我留下了這段代碼在我的精靈類: canvas.bitmapData.copyPixels(_bitmapData, _bitmapData.rect, destination, null, null, true);

我緩存_bitmapData.rect的結果爲對象的創建和我的新的矩形調用六千人突然從剖析器中刪除。

見鬼,爲什麼會BitmapData.rect創建一個新的矩形?有沒有辦法檢查覈心庫或什麼,並確認這是真的?這似乎令人困惑。

+0

你絕對,100%肯定它是導致問題的矩形數據?我也會完全困惑。有沒有可能將全部的來源用於檢查? – Nate

回答

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.colorTransform:每個接入
  • DisplayObject.filters返回新ColorTransform實例:在每個接入
  • 返回新Array實例......你可以找到很多其他的情況下,當你得到一個內部對象的副本。

在所有這些情況下類的保護自己不被打破。試想一下:當一個類使用聚合時,它不能按原樣公開它的聚合實例,因爲否則當內部對象發生變化時,需要通知主類的變化。這是很多邏輯來更新和驗證每個聚合實例的每個字段中的更改。

0

有趣的觀察。

可以使用===運算符來檢查是否有任何Object的兩個實例是相同的。

這可能是因爲BitmapData內部使用不同的數據結構,以保持其可視狀態。 rect屬性必須作爲getter函數來實現。然而,人們會認爲,因爲BitmapData的尺寸是不變的,所以對象永遠不需要被重新創建,甚至根本不需要重新計算。

編輯:rect財產上BitmapData是隻讀的(沒有setter),但在Rectangle屬性都沒有。創建Rectangle的新實例可確保外部對象不能進行突變。

+0

實際上沒有必要嚴格比較。只有比較不同(或未知)類型的值並且希望避免類型轉換時,它纔是有用的。在這裏,我們將一個矩形與一個矩形進行比較,'=='和'==='產生相同的結果。 –

+0

這是真的,在這種情況下,類型是相同的。然而,爲了完整起見,爲什麼不使用'==='? – Peter

+0

@Nox Noctis,你同意嗎? – Peter

1

Bethanny安妮說:

見鬼,爲什麼會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實例。最後說明:這涉及'傳值'(原始類型)和'傳遞參考'(複雜類型)變量。欲瞭解更多信息請查看谷歌或其他職位上的計算器:Pass by reference or pass by value?

+0

優秀的點,我想這可能也是原因。雖然'Rectangle'不是原始類型,'BitmapData'返回一個新的實例,給它一個類似的按值傳遞效果 - 所以現在類似於DisplayObject的''x''屬性,你不能通過存儲一個在另一個變量中引用。無論如何,在「矩形」的情況下,爲什麼哦爲什麼有人會改變這樣的值......也許要做一些矩陣運算。 ;) – Peter

+0

此外,'rect'屬性本質上是隻讀的(雖然Rectangle實例上的屬性不是)。創建並返回一個新的Rectangle實例是執行此操作的唯一方法。你絕對正確! – Peter

+0

這是爲什麼被低估?請解釋一下自己? – Peter

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的新實例。

+0

我們在哪裏可以找到這個源代碼? – Peter

+0

只有一種方法可以得到它 - 反向工程'playerglobal.swc' :)。 – surlac

+0

真棒!我只是試着用Trillix做這個。 :D – Peter