7

私が遭遇した単なる概念的な質問。smart_ptr私の現在のプロジェクトでは、ブーストとptr_containerライブラリを使いすぎているように感じます。私はboost::ptr_vectors 多くの異なるオブジェクトを作成し、transfer()メソッドを呼び出して、特定のポインターboost::ptr_vectorを別のポインターに移動していました。

ヒープに割り当てられたオブジェクトの所有権を明確に示すことが重要であると私は理解しています。

私の質問は、これらのブーストライブラリを使用して、オブジェクトに属するヒープ割り当てメンバーを作成しget()、処理を行うときにこれらのメンバーへの通常のポインタを使用することが望ましいかどうかです。

たとえば...ゲームには、それに属するタイルのコレクションが含まれている場合があります。これらのタイルをで作成することは理にかなっているかもしれませんboost::ptr_vector。ゲームが終了すると、これらのタイルは自動的に解放されます。

ただし、これらのタイルを一時的にBagオブジェクトに入れたい場合は、バッグ内に別のタイルを作成しboost::ptr_vectorてを介してゲームのタイルをバッグに転送するか、Tiles*がゲーム内のタイルを参照transfer()する場所を作成して渡す必要があります。std::vector<Tile*>バッグに?

ありがとう。

**編集私の例では、ゲームにはメンバーとしてBagオ​​ブジェクトが含まれることを指摘しておく必要があります。バッグは、ゲームが所有するタイルでのみ満たされます。したがって、バッグはゲームなしでは存在しません。

4

8 に答える 8

16

所有権の明確な移転がある場合にのみ、所有権のあるスマートポインターとポインターコンテナーを使用する必要があります。オブジェクトが一時的であるかどうかは関係ありません。重要なのは、オブジェクトが所有権を持っているかどうか(したがって、前の所有者が所有権を放棄するかどうか)です。

他の関数に渡すためだけにポインタの一時ベクトルを作成し、元ptr_vectorのオブジェクトがそれらすべてのオブジェクトを参照している場合、所有権の譲渡はありません。したがってvector、生のオブジェクトを使用するのと同じように、一時オブジェクトにはプレーンを使用する必要があります。単一のオブジェクトをptr_vector、ポインターを受け取るがどこにも格納しない関数に渡すためのポインター。

于 2009-09-03T17:35:10.240 に答える
6

私の経験では、3つの主要な所有パターンが発生します。それらをツリー、DAG、グラフと呼びます。

最も一般的なのは木です。親は子を所有し、子は子を所有します。auto_ptr、scoped_ptr、ベアポインター、およびブーストptr_xクラスは、ここで通常表示されるものです。私の意見では、裸のポインタは所有権のセマンティクスをまったく伝えないため、一般的には避ける必要があります。

2番目に一般的なのはDAGです。これは、所有権を共有できることを意味します。親が所有する子は、親が所有する他の子の子である場合もあります。ここでは、TR1およびブーストshared_ptrテンプレートが主なアクターです。参照カウントは、サイクルがない場合に実行可能な戦略です。

3番目に一般的なのは完全グラフです。これはあなたがサイクルを持つことができることを意味します。これらのサイクルを中断し、いくつかの考えられるエラーの原因を犠牲にしてDAGに戻るためのいくつかの戦略があります。これらは通常、TR1またはboostのweak_ptrテンプレートで表されます。

weak_ptrを使用してDAGに分解できない完全グラフは、C++では簡単に解決できない問題です。唯一の良いハンドラーはガベージコレクションスキームです。それらはまた最も一般的であり、他の2つのスキームも非常にうまく処理することができます。しかし、それらの一般性には代償が伴います。

私の意見では、ポインタのコンテナではなくオブジェクトのコンテナを実際に使用する必要がない限り、ptr_xコンテナクラスまたはauto_ptrを使いすぎることはできません。shared_ptrは使いすぎる可能性があります。本当にDAGが必要かどうかを慎重に検討してください。

もちろん、ブーストptr_xクラスの代わりにscope_ptrsのコンテナーを使用する必要があると思いますが、C++0xを待つ必要があります。:-(

于 2009-09-03T17:52:14.863 に答える
5

ほとんどの場合、あなたが探している解決策は

std::vector<Tile>

ほとんどの場合、ポインタは必要ありません。ベクターは、含まれているオブジェクトのメモリ管理をすでに処理しています。タイルはゲームが所有していますね。これを明示的にする方法は、オブジェクト自体をゲームクラスに配置することです。通常、ポインターと動的に割り当てられた個々のオブジェクトが必要なのは、1)ポリモーフィズム、または2)共有所有権が必要な場合のみです。

ただし、ポインタは例外であり、ルールではありません。

于 2009-09-03T18:38:58.213 に答える
1

boost::ptr_vectorポインタのベクトルを使用するセマンティクスを改善するためにのみ役立ちます。あなたの例で、ベクトルの一時的なセットが使用されている間に元の配列が破壊される可能性がある場合は、使用中にベクトルshared_ptrが削除されないように、必ずsのベクトルを使用する必要があります。そうでない場合は、ポインタの単純な古いベクトルが適切である可能性があります。ベクトルを使用するコードの見栄えを除いて、選択するかどうかstd::vectorboost::ptr_vector重要ではありません。

于 2009-09-03T17:36:34.493 に答える
1

ゲームタイルの例では、私の最初の本能は、またはptr_vectorvector<Tile>ではなく、を作成することです。vector<Tile*>次に、所有権をまったく気にせずに、タイルへのポインターを好きなように使用します。ただし、ポインターを保持するオブジェクトがタイルのベクトルよりも長持ちしない場合に限ります。ゲームが終了したときにのみ破壊されるとおっしゃっていたので、難しいことではありません。

もちろん、これが不可能な理由があるかもしれません。たとえば、タイルは多形の基本クラスであり、タイル自体はすべて同じクラスではないためです。しかし、これはJavaではなくC ++であり、すべての問題が常に動的ポリモーフィズムを必要とするわけではありません。ただし、本当にポインターが必要な場合でも、ポイントされたオブジェクトのスコープとストレージ期間がポインターのスコープと使用期間よりも広いと理解されていれば、所有権のセマンティクスなしでそれらのポインターのコピーを作成できます。

int main() {
    vector<Tile*> v;
    // fill in v, perhaps with heap objects, perhaps with stack objects.
    runGame(v);
}

void runGame(const vector<Tile*> &v) {
    Tile *firsttile = v[0];
    vector<Tile*> eventiles;
    eventiles.push_back(v[2]);
    eventiles.push_back(v[4]);
    // and so on. No need to worry about ownership, 
    // just as long as I don't keep any pointers beyond return.
    // It's my caller's problem to track and free heap objects, if any.
}
于 2009-09-03T17:56:37.520 に答える
1

ゲームがタイルを所有している場合、ゲームはそのタイルの削除に責任があります。

バッグが実際にオブジェクトを所有することはないように思われるので、オブジェクトを削除する責任を負わないようにする必要があります。したがって、Gameオブジェクト内でptr_vectorを使用します。ただし、バッグにはstd::vectorを使用してください。

注:バッグを使用している人に、バッグからタイルへのポインターを取得させることは決してありません。バッグからタイルへの参照のみを取得できる必要があります。

于 2009-09-03T20:00:16.723 に答える
0

タイルがバッグに入れられ、誰かがバッグを盗んだ場合、あなたはすべてのタイルを失います。したがって、タイルは一時的ではありますが、短時間はバッグに属します。ここで所有権を譲渡する必要があると思います。

しかし、この特定のケースでなぜそれが必要なのかわからないので、所有権を台無しにしない方が良い意見です。舞台裏に何かがある場合は、続けて、選択してください。

于 2009-09-03T18:01:35.293 に答える
0

ヒープに割り当てられたTに直接ジャンプする代わりにベクトルを使用するのは良い本能であることに同意しますが、コピーの構築には費用がかかる一方で、タイルがタイプであることが簡単にわかります。これにより、ベクトルの成長戦略が実用的でなくなる可能性があります。もちろん、それはベクトルではなくリストで解決するのが最善かもしれません...

于 2009-09-09T18:52:11.197 に答える