shared_ptr<> is to weak_ptr<> as unique_ptr<> is to… what?

后端 未结 8 1110
慢半拍i
慢半拍i 2020-12-01 03:59

In C++11, you can use a shared_ptr<> to establish an ownership relation with an object or variable and weak_ptr<> to safely reference t

8条回答
  •  既然无缘
    2020-12-01 04:45

    While you can't get a "weak" pointer to a uniquely owned object for free, the concept is useful and is used in a couple systems. See Chromium's WeakPtr and QT's QPointer for implementations.

    Chromium's WeakPtr is implemented intrusively by storing a shared_ptr inside the weak-referenceable object and marking it invalid when the object is destroyed. WeakPtrs then reference that ControlBlock and check whether it's valid before handing out their raw pointer. I assume QT's QPointer is implemented similarly. Because ownership isn't shared, the original object is destroyed deterministically.

    However, this means that dereferencing the WeakUniquePtr isn't thread-safe:

    Thread 1:

    unique_ptr obj(new MyObject);
    thread2.send(obj->AsWeakPtr());
    ...
    obj.reset();  // A
    

    Thread2:

    void receive(WeakUniquePtr weak_obj) {
      if (MyObject* obj = weak_obj.get()) {
        // B
        obj->use();
      }
    }
    

    If line A happens to run concurrently with line B, thread 2 will wind up using a dangling pointer. std::weak_ptr would prevent this problem by atomically taking a shared owning reference to the object before letting thread 2 use it, but that violates the assumption above that the object is owned uniquely. That means that any use of a WeakUniquePtr needs to be synchronized with the destruction of the real object, and the simplest way to do that is to require that they're done in a message loop on the same thread. (Note that it's still completely safe to copy the WeakUniquePtr back and forth across threads before using it.)

    One could imagine using a custom deleter in std::unique_ptr to implement this using standard library types, but that's left as an exercise for the reader.

提交回复
热议问题