【问题标题】:How can I break this std::shared_ptr reference cycle?如何打破这个 std::shared_ptr 参考周期?
【发布时间】:2016-05-30 19:19:13
【问题描述】:

通常,我会用weak_ptr 打破shared_ptrs 的循环。但在这个例子中我看不到如何做到这一点:

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;
};

AB 等之间从来没有任何循环。唯一的循环是对Cache 的反向引用。只要任何人(Cache 本身除外)拥有shared_ptr&lt;C&gt;Cache 就需要保持活力,因此仅使用weak_ptr&lt;Cache&gt; 将不起作用。例如:

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
}

我知道通常这需要垃圾收集器,但我希望在这种特定情况下,可以使用 shared_ptraliasing constructor (8) 或其他东西来完成一些技巧。

【问题讨论】:

  • 隐藏的循环引用实际上无法用标准 c++ shared_ptr / weak_ptr 成语解决。你必须改变你的设计。
  • 由于ccache 将始终相互引用,也许您应该创建一个包含CacheC 的新类C,并让C::cacheCache::c 使用它的引用计数 (std::shared_ptr&lt;C&gt;(cwd, &amp;cwd-&gt;c))

标签: c++ shared-ptr reference-counting


【解决方案1】:

“只要任何人(缓存本身除外)拥有shared_ptr&lt;C&gt;,缓存就需要保持活动状态。”

这表明 C 控制了整个结构的最终寿命。 所以,缓存不应该组成C吗?

【讨论】:

  • 只要有人拥有shared_ptr&lt;Cache&gt;C 也必须保持活力。两者都不是特别的。
  • @TavianBarnes 你是说只要指向结构任何部分的共享指针有效,整个结构就有效吗?
  • 理想情况下,是的,这就是我要说的。
  • @TavianBarnes auto c = make_cache()-&gt;c; 必须返回有效 c 的约束是问题所在,因为在函数返回缓存指针之前,缓存是 c 的唯一所有者。这与如果缓存拥有唯一指向它的指针,则必须删除 c 的约束是不一致的。
  • 对不起,这个约束不是我的意思。我的意思是,只要有人持有指向CCache 的指针,c 就必须存在。如果没有人再持有指向Cache 的指针,那么Cache::c 不应该保持C 活着。
猜你喜欢
  • 1970-01-01
  • 2012-07-27
  • 2017-06-18
  • 2013-02-08
  • 2012-12-26
  • 1970-01-01
  • 2015-10-14
  • 1970-01-01
相关资源
最近更新 更多