9

私はの循環参照を試していて、boost::shared_ptr次のサンプルを考案しました。

class A{ // Trivial class
public:
    i32 i;
    A(){}
    A(i32 a):i(a){}
    ~A(){
        cout<<"~A : "<<i<<endl;
    }
};

shared_ptr<A> changeI(shared_ptr<A> s){
    s->i++;
    cout<<s.use_count()<<'\n';

    return s;
}

int main() {

    shared_ptr<A> p1 = make_shared<A>(3);
    shared_ptr<A> p2 = p1;
    shared_ptr<A> p3 = p2;
    shared_ptr<A> p4 = p3;

    p1 = p4; // 1) 1st cyclic ref.
    cout<<p1.use_count()<<'\n';

    p1 = changeI(p4); // 2) 2nd cyclic ref.

    cout<<p1.use_count()<<'\n';

//  putchar('\n');
    cout<<endl;
}

どの出力

4
5
4

~A : 4

で述べた循環参照を誤解したのboost::shared_ptrでしょうか?p1なぜなら、アフターコメント1)とへの間接参照については、異なる出力思考を期待していたから2)です。したがって、このコードは必要ありませんboost::weak_ptrweak_ptrでは、 sが必要となる循環参照は何ですか?

前もって感謝します。

4

2 に答える 2

23

はい、あなたはこれを誤って解釈しました。あなたの例では、すべてのポインターが同じオブジェクトを指しており、サイクルを形成していません。

p4からp2への割り当ては、これらのポインターが最初からすでに等しいため、何もしません。

これが実際の循環参照の例です。おそらくそれで問題が解決するでしょう。

struct A
{
  std::shared_ptr<A> ptr;
};

void main()
{
  std::shared_ptr<A> x=std::make_shared<A>();
  std::shared_ptr<A> y=std::make_shared<A>();

  x->ptr = y; // not quite a cycle yet
  y->ptr = x; // now we got a cycle x keeps y alive and y keeps x alive
}

これをさらに簡単にすることもできます。

void main()
{
  std::shared_ptr<A> x=std::make_shared<A>();

  x->ptr = x; // never die! x keeps itself alive
}

どちらの例でも、mainを離れた後でも、shared_ptrs内のオブジェクトが破棄されることはありません。

于 2012-09-09T12:01:24.867 に答える
2

指摘したいのですが、出力の2行目がa5であり、a4ではない理由は、s->i++増加のためではなく、shared_ptr<A> sパラメーターが値によって渡されているためです。

電話すると

p1 = changeI(p4); // 2) 2nd cyclic ref.

p4関数のスコープ中にshared_pointer一時的に1ずつ増加して、さらに別のにコピーされます。use_count

たぶん私はここで明らかなキャプテンを演じています(;

于 2017-10-26T19:12:10.813 に答える