代码之家  ›  专栏  ›  技术社区  ›  user2891462

普通引用而不是弱ptr来打破循环依赖

  •  1
  • user2891462  · 技术社区  · 8 年前

    看一看 std::weak_ptr 我在几个地方看到,它可以用来打破由于使用 std::shared_ptr 是的。例如,请参见这两个公认的答案: [1] 我是说, [2] 是的。

    以最后一个引用的答案为例,建议的解决方案是:

    #include <memory>
    #include <iostream>
    
    struct B;
    struct A {
      std::shared_ptr<B> b;  
      ~A() { std::cout << "~A()\n"; }
    };
    
    struct B {
      std::weak_ptr<A> a;
      ~B() { std::cout << "~B()\n"; }  
    };
    
    void useAnB() {
      auto a = std::make_shared<A>();
      auto b = std::make_shared<B>();
      a->b = b;
      b->a = a;
    }
    
    int main() {
       useAnB();
       std::cout << "Finished using A and B\n";
    }
    

    不过,这感觉有点过头了,为什么不简单地使用一个引用呢?我明白在这个例子中 b->a 不是在构造函数中设置的,所以引用不会真正剪切它,所以我的问题是:

    是否有理由使用 性病:虚弱 而不是引用 如果我们可以在 构造器?

    注: 我明白 性病:虚弱 保存可以失效的引用。我的问题只涉及到当问题的关键是打破循环依赖时的有用性。

    3 回复  |  直到 8 年前
        1
  •  1
  •   StoryTeller - Unslander Monica    8 年前

    下面是一个稍加修改的函数:

    void useAnB() {
      std::shared_ptr<B> oops;
      {
          auto a = std::make_shared<A>();
          auto b = std::make_shared<B>();
          a->b = b;
          b->a = a;
          oops = b;
      }
      // use oops->a 
    }
    

    你怎么知道 oops->a 如果对象是纯指针或引用,则不再引用有效对象?

        2
  •  1
  •   molbdnilo    8 年前

    你不能检查一个引用(或普通指针)是否引用了一个已有的对象,你不能“重新引用”一个引用,例如在一个赋值中。

        3
  •  0
  •   catnip    8 年前

    我明白 std::weak_ptr 保存可以失效的引用。我的问题只涉及到当问题的关键是打破循环依赖时的有用性。

    好吧,如果你有一个循环依赖关系(或者即使你没有),并且你想把一个对“master”对象的引用存储在其他地方,这样你就可以访问它,并且你确定当你想这样做的时候,这个对象不会消失,那么是的,我会使用一个引用,因为:

    • 比较便宜
    • 它可以避免使主对象成为 shared_ptr 首先(而且这些东西本身很贵)

    归根结底,这是为了让你的对象最好地完成你需要他们做的任何工作。当然, 性病:虚弱 不是每个少女的祈祷都能得到回应。

    推荐文章