1

画像を表す一連のクラスを作成しています。このクラスのアプリケーションの 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 オブジェクトへのポインターをユーザーが保存する可能性があります。

1 つのオプションは、次のように、完了したらピクセルをチェックインするようにユーザーに要求することです。

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 を Image として渡すことができるようにしたいと考えています。

ありがとう。

4

3 に答える 3

5

2 つの可能性 (少なくとも):

  • 使用shared_ptr(boostまたはstd):

    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。これは、 aPixelが常に見つかることが期待される場合、または存在しないことを示すために返される可能性のあるデフォルト値がある場合にのみ実行可能です。

マイナーポイント、すべてのメンバー関数は変更されないことを意味するImageため、それらを作成することを検討してくださいconst

于 2012-06-04T07:34:25.520 に答える
1

ベクトルが破棄されると明らかに無効になるようなもののイテレータはstd::vector、これがあなたのケースとどのように違うのかわかりません。

所有権を譲渡していないことが明確に示されているため、参照によってピクセルを返すことをお勧めします。また、無効化の動作に関する適切なドキュメントを提供してください。


に対する推奨事項がありましたshared_ptr。その方法を取る場合は、所有権がイメージに属しているため、 aweak_ptrではなくa を返すことをお勧めします。shared_ptr

于 2012-06-04T07:41:13.367 に答える
1

RAIIは間違いなくここに行く方法です. Pixel クラスはimage.returnPixel(this)そのデストラクタを呼び出してfindPixelshared_ptr<Pixel>. ユーザーが完了してもピクセルが削除されない可能性がある場合は、代わりに、ピクセルを削除せずに呼び出すカスタム デリータを含む shared_ptr を返すことができますreturnPixel

于 2012-06-04T07:33:57.013 に答える