0

typeAggregatorと oneがあるとしAggregateeます。前者はshared_ptrs によって後者のコレクションを知っています。後者には、前者への一意のバック ポインターがあります。

struct Aggregatee {
  private:
    Aggregator& aggregator;
    Aggregatee(Aggregator& aggregator)
      : aggregator{aggregator} {
      // PROBLEM HERE:
      //   I want to put `this` into the aggregation list,
      //   but I have no clue how to properly refer to `this`
      //   because I don't have the smart pointer object, yet.
    }
    Aggregatee(Aggregatee const& from) { /* ... */ }
  public:
    template <typename Args...>
    static std::shared_ptr<Aggregatee> create(Args... args) {
      return std::make_shared<Aggregatee>(args...);
    }
};

struct Aggregator {
  std::set<std::shared_ptr<Aggregatee>> aggregation;
};

明らかに、プライベート関数を使用しAggregateeAggregatorオブジェクトへの登録を延期できますが、オブジェクトが一時的に一貫性のない初期化されるため、2 フェーズのようなにおいがします。make_sharedregister

これに対する既知の解決策はありますか?

4

3 に答える 3

0

アプリケーションによっては、静的 create メソッドを Aggregatee から通常のメンバー メソッド Aggregator に移動できます。次に、shared_ptr を作成し、同じメソッドに保存できます。

これは、Aggregatee が常に Aggregator に関連付けられていることを前提としています。

于 2012-09-07T02:00:46.687 に答える
0

回避しようとしているのは、実際には非常に一般的なパターンです。アグリゲーター (コンテナー) が作成され、次に集約 (要素) が作成されてコンテナーに挿入されます。コンストラクターに渡されたバック ポインターを使用して要素を作成し、コンテナーまたはバックポインターに挿入することができます。

たとえば、バックポインターを持つバイナリ ツリーを考えてみましょう。要素は、親ノードへのポインターを持つリーフで作成され、ポインターはすぐに親ノードに格納されます。

shared_ptrあなたの特定の質問に関しては、オブジェクトが作成される前にオブジェクトを取得することはできませんenable_shared_from_this

于 2012-09-07T03:42:41.247 に答える
0

侵入型の共有ポインターを使用できます。参照カウントは共有オブジェクト内に存在するため、Aggregatee は独自のコンストラクター内でそれ自体への共有ポインターを作成できます。

Boost には、侵入型のポインター型の例があります。または、独自のものを非常に簡単にロールバックできます。

http://www.boost.org/doc/libs/1_51_0/libs/smart_ptr/intrusive_ptr.html

// shared base type contains the reference counter; how you implement the
// reference counting depends on your implementation.
struct Aggregatee : public shared {
  private:
    Aggregator& aggregator;

    Aggregatee(Aggregator& aggregator) : aggregator{aggregator} {
      // Boost allows a raw pointer to be implicitly cast to an intrusive
      // pointer, but maybe your intrusive pointer type won't.
      aggregator.aggregation.insert(intrusive_ptr<Aggregatee>(this));
    }

    Aggregatee(Aggregatee const& from) { /* ... */ }

  public:
    template <typename Args...>
    static intrusive_ptr<Aggregatee> create(Args... args) {
      return new intrusive_ptr<Aggregatee>(args...);
    }
};

struct Aggregator {
  std::set<intrusive_ptr<Aggregatee>> aggregation;
};

注意しなければならないことの 1 つは、Aggregatee が構築後に実際にスマート ポインターに格納されることです。

Aggregatee aggregatee(aggregator);  // Very bad!
intrusive_ptr<Aggregatee> aggregatee(new Aggregatee(aggregator));  // Good

また、Aggregatee が完全に構築されるまで、Aggregator が intrusive_ptr を保持していることを確認してください。そうしないと、コンストラクターが終了する前に Aggregatee が破棄されてしまいます!

したがって、このアプローチにはいくつかの注意点がありますが、私が知る限り、これはあなたが求めたものを達成するのに最も近いものです.

于 2012-09-07T15:34:41.973 に答える