2012-06-04 51 views
1

我正在製作一組類以表示圖像。這個類的其中一個應用就是通過一組平鋪的圖像繪製圖片。抽象圖像類看起來是這樣的:如何應對返回指針的生命週期?

class Image 
{ 
public: 
    virtual Pixel* findPixel(Point p) =0; 
    virtual bool isDrawable(Point p) =0; 
    virtual bool contains(Point p) =0; 
}; 

我預見的問題是,如果我是這樣的一類:

class TiledImage : public Image 
{ 
    std::vector<Image*> tiles; 

public: 
    Pixel* findPixel(Point p) 
    { 
     // find the tile that contains the point. 
     // ask it for the pixel that contains the point. 
     // return the pixel. 
    } 

    // etc.... 

}; 

,旨在創建,保存和刪除第(磚)根據需要可以存儲非常大的圖像,則用戶可能會存儲指向可能最終不再存在的Pixel對象的指針。

一種選擇是要求用戶檢查像素背的時候都在做,比如:

Pixel* p = image.findPixel(aPoint); 
// do stuff 
image.returnPixel(p); // p is not guaranteed to be valid after this point. 
p->doSomething(); // this is not guaranteed to work. 

我真的不喜歡這一點,因爲如果用戶不返回該像素,則它真的可能會混淆平鋪圖像的操作 - 忘記返回像素會導致它完全鎖定,因爲它無法刪除不再需要的平鋪。它們將被鎖定以保證指向像素的指針保持有效。鎖定的原因可能對用戶難以發現。

此外,這種擔心是一種專業化。在典型情況下圖像消失之前,您不會指望像素消失。

有沒有更好的方法來處理這種情況?智能指針?不要以某種方式返回參考?使TiledImage從Image繼承是否沒有意義?我當然希望能夠將TiledImage作爲圖片傳入,因爲我期望圖片非常大。

謝謝。

回答

1

RAII確定了這裏的方法。您的Pixel類應在其析構函數中調用image.returnPixel(this)findPixel應返回shared_ptr<Pixel>。如果用戶完成後可能不會刪除像素,則可以使用不刪除像素的自定義刪除程序返回shared_ptr,而是調用returnPixel

5

兩種可能性(至少):

  • shared_ptr使用(或者booststd):

    std::vector<shared_ptr<Image>> tiles; // No longer have to explicitly 
                 // delete the elements. 
    
    shared_ptr<Pixel> findPixel(Point p) 
    { 
        ... 
    } 
    
    shared_ptr<Pixel> p = image.findPixel(aPoint); 
    p->doSomething(); // Fine, as the internal pointer will not be 
            // deleted due to use of the smart pointer. 
    
  • 回報Pixel的副本。這隻有在預期找到Pixel或者存在可用於指示不存在的可用缺省值時纔可行。

小點,所有的成員函數意味着他們不改變Image所以考慮讓他們const

1

對於像std::vector這樣的東西,迭代器在向量被銷燬時顯然是無效的,我不明白這與你的情況有什麼不同。

我的建議是通過引用返回像素,因爲這清楚地表明它沒有移交所有權。另外,請提供有關失效行爲的良好文檔。


已經有建議shared_ptr,如果你採取的路線似乎是個不錯的決定返回shared_ptrweak_ptr而不是作爲所有權屬於圖像。

+0

我擔心交給Pixel引用,因爲如果用戶不小心寫入Pixel p = image.findPixel(...)而不是Pixel&p = image.findPixel(...),他們將不會更改它們的圖像改變像素值。 – user487100

+0

@ user487100別擔心,所有返回引用的函數都有'問題',但我從來沒有見過任何人對此感到困惑。 – Pubby