3

私はこれを理解することはできません..単純なものが欠けているように見えますか? MakePointToSameValueポイントで何を入れますか(1)

  • b.ptr と c.ptr の両方が a.ptr と同じものを指している
  • 言い換えると、a.ptr.get() == b.ptr.get() == c.ptr.get()
  • b.ptr と c.ptr が最初に指していた値が削除される

?

struct Test
{
public:
  Test( int val ) :
    ptr( std::make_shared< int >( val ) )
  {
  }

  void MakePointToSameValue( Test& other )
  {
    //what do I put here?
    //other.ptr = this->ptr; //doesn't do it
  }

private:
  std::shared_ptr< int > ptr;
};

Test a( 0 );
Test b( 5 );
Test c( b );

b.MakePointToSameValue( a );

//(1)

c を変更しないため、ptr のコピーは機能しません (まあ、c.ptr の参照カウントは 1 減ります)。簡単にするために使用することに注意してくださいint。ただし、コピーできない型でも機能するはずです。

なんで?ある種のコンパイラで使用するための、あらゆるタイプの値を表すクラスがあります。実際の値も格納方法も、インスタンス化された時点でわかります。わかるのは型だけです。したがって、クラスは、後で決定される値のプレースホルダーを含む shared_ptr を格納します (ポインターまたは参照として渡されたときに関数定義の引数をコンパイルすることに相当します: コンパイラーは型のみを認識し、それ以上は認識しません)。実行時に、プレースホルダーを実際の値に置き換える必要があります。

一日の新たなスタートを編集して、これを思いつきました。私はそれが簡単であることを知っていました。

void MakePointToSameValue( Test& other )
{
  other.ptr.swap( ptr );
  ptr.reset();
  ptr = other.ptr;
}

追加の質問は次のとおりです。上記は、標準に準拠したポインターに対して期待どおりに機能しますか?

4

2 に答える 2

3

ここでは、2 レベルの間接化が必要です。shared_ptrすべてのオブジェクトがカウントと実際の値へのポインターを含む共通のメタデータ ブロックを指していることは正しいですが、別のオブジェクトを指すようにそのブロックを更新しようとすると、2 つのメタデータ ブロックが指すようになります。同じ値であり、それぞれが参照カウントとは何かについて独自の異なる考えを持っています。各メタデータ ブロックを使用するオブジェクトの正しい数 (参照カウントと一致するという意味で) があるshared_ptrため、各ブロックのカウントは最終的にゼロになりますが、カウントに到達する最後のブロックがどのブロックであるかを知る方法はありません。ゼロ (したがって、値を削除する必要があります)。そのshared_ptrため、メタデータ内のオブジェクト ポインターを変更することはできません。のみを関連付けることができますshared_ptr新しいメタデータ ブロック、新しいカウント、新しいオブジェクトを使用します。また、同じオブジェクトへの他のポインターは影響を受けません。

これを行う正しい方法は、間接化の 2 番目のレイヤーを使用することです ( shared_ptr<shared_ptr<int> >)。そうすれば、オブジェクトごとに正確に 1 つのメタデータ ブロックと正確に 1 つのカウントが存在します。更新は中間の shared_ptr に対して行われます。

于 2012-07-04T16:03:11.320 に答える
1

私があなたの要件を理解している限り、shared_ptrそのようなメカニズムは含まれていません。また、通常のタイプもありません。この動作が必要な場合は、自分でコーディングする必要があります。私の提案: private static を追加しますstd::list<std::weak_ptr<Test>> registry。各Testインスタンスをregistryコンストラクタのリストに追加して登録し、デストラクタで必ず削除してください。

次に、そのレジストリを使用しMakePointToSameValueてすべてのインスタンスを反復処理し、 の値をリセットしますptr

効率に関心があり、インスタンスが 3 つより少し多い場合は、listunordered_set;に置き換えます。おそらく、クラスunique_ptrではなく使用shared_ptrしますTest

追加の質問への回答: いいえ、機能しません。のドキュメントを見てくださいreset(): 特定の 1 つのインスタンスをリセットしますshared_ptr: 他のインスタンスとは何もしません (そして何も知りません)。制御ブロックの参照カウントがゼロになると、さらにポインティが破棄されますが、それだけです。

于 2012-07-03T12:19:20.080 に答える