Normalerweise würde ich einen Zyklus von shared_ptr
s mit weak_ptr
brechen. Aber ich kann nicht sehen, wie das in diesem Beispiel zu tun:Wie kann ich diesen Referenzzyklus std :: shared_ptr unterbrechen?
struct A;
struct B;
struct C;
struct D;
struct Cache {
std::shared_ptr<A> a;
std::shared_ptr<B> b;
std::shared_ptr<C> c;
std::shared_ptr<D> d;
};
struct A {
};
struct B {
// Same 'a' as in the Cache
std::shared_ptr<A> a;
};
struct C {
// Holds a backreference to the cache
std::shared_ptr<Cache> cache;
};
struct D {
// Same 'c' as in the cache
std::shared_ptr<C> c;
};
Es gibt nie Zyklen zwischen dem A
, B
usw. Die einzigen Zyklen sind Rückreferenzierungen zum Cache
. Die Cache
muss am Leben bleiben, solange jemand (außer der Cache
selbst) eine shared_ptr<C>
hat, so dass nur die Verwendung weak_ptr<Cache>
wird nicht funktionieren. Zum Beispiel:
std::shared_ptr<Cache> make_cache() {
auto cache = std::make_shared<Cache>();
cache->a = std::make_shared<A>();
cache->b = std::make_shared<B>();
cache->b->a = cache->a;
cache->c = std::make_shared<C>();
cache->c->cache = cache;
cache->d = std::make_shared<D>();
cache->d->c = cache->c;
return cache;
}
void use_cache() {
auto a = make_cache()->a;
// No need to keep the Cache around
auto b = make_cache()->b;
// b->a must be valid
auto c = make_cache()->c;
// c->cache must be valid
auto d = make_cache()->d;
// d->c (and therefore d->c->cache, etc.) must be valid
}
Ich verstehe, dass in der Regel würde dies einen Garbage Collector erfordern, aber ich bin in diesem speziellen Fall der Hoffnung, es gibt einige Tricks, die mit shared_ptr
‚s aliasing constructor (8) oder etwas getan werden können.
Versteckte zyklische Referenzen können tatsächlich nicht mit den Standard-C++ 'shared_ptr' /' weak_ptr'-Idiomen gelöst werden. Sie müssen Ihr Design ändern. –
Da 'c' und' cache' immer aufeinander verweisen, sollten Sie vielleicht eine neue Klasse 'CacheWithData' erstellen, die' Cache' und 'C' enthält und' C :: cache' und 'Cache :: c' Verwenden Sie die Referenzzahl ('std :: shared_ptr (cwd, & cwd-> c)') –