我可以在不删除对象的情况下重置 shared_ptr 以便 weak_ptr 失去对它的引用吗

Can I reset shared_ptr without deleting object so that weak_ptr loses a reference to it

我想在不删除其对象的情况下重置 shared_ptr,并让其中的 weak_ptr 失去对它的引用。但是shared_ptr因为某些原因没有release()成员函数,所以不能直接做。最简单的解决方案就是调用 weak_ptr 的 reset() 但拥有 shared_ptr 并想要释放它的 class 不知道哪个 class 有weak_ptr 个。在这种情况下如何实现?

我明白了为什么shared_ptr没有发布功能但是unique_ptr。在我的例子中,只有一个实例拥有一个指针,但是 shared_ptr 可以被多个实例拥有,然后释放就没有意义了。但是如果 shared_ptr 没有那个功能,我如何在不删除对象的情况下切断与 weak_ptr 的连接?

shared_ptr<int> A = make_shared<int>(100);
weak_ptr<int> B = A;

// I want something like this! but shared_ptr doesn't have release function..
int* releasedData = A.release();
A.reset(releasedData);

if (shared_ptr<int> C = B.lock)
{
    // B already lost a reference, so it should never reach here
}

背景

存储大数组指针的class的共享指针与其他classes共享。共享指针作为弱指针传递给它们,共享指针的所有者 class 不知道这些 class。所有者 class 的多个实例在运行时被激活和停用。因为实例的初始化成本很高,所以我使用对象池模式:我每次使用它时都重用这些实例而不是 creating/deleting 。这里的问题是,当所有者 class 的实例被停用时,它应该被视为已删除(尽管它仍然保留数据),因此其他 classes 对数据应该失去参考。重置共享指针使之成为可能,但我不想这样做,因为数据很大。

我可以让管理器class跟踪哪个弱指针指向哪个共享指针,但我想知道是否可以通过其他方法解决这个问题。

您可以使用带有自定义删除器的 shared_ptr 来防止对象被销毁:

shared_ptr<int> A = shared_ptr<int>(new int(100), [](int*){});
weak_ptr<int> B = A;

// Save the pointer that you otherwise would lose:
int* releasedData = A.get();
A = shared_ptr<int>(releasedData, [](int*){});;

if (shared_ptr<int> C = B.lock())
{
    // B already lost a reference, so it should never reach here
}

但不要忘记通过任何其他方式删除对象。例如:

shared_ptr<int> realOwner(new int(100));

shared_ptr<int> A = shared_ptr<int>(realOwner.get(), [](int*){});
weak_ptr<int> B = A;

std::shared_ptrstd::weak_ptr是模仿RAII的概念。当你使用 std::shared_ptr 时,你已经决定它拥有资源,并且它应该在销毁时释放资源。您面临的笨拙是由于对 RAII 的反叛:您希望 std::shared_ptr 拥有资源,但有时并非如此。

解决方案是将您的对象池重新构造为分配器。假设你有

struct obj_t { /* ... */ };

struct pool_t {
    obj_t* acquire();      // get an object from the pool
    void release(obj_t*);  // return the object to the pool
    // ...
};

然后你的 std::shared_ptr 看起来像

auto d = [&pool](auto p){ pool.release(p); };
std::shared_ptr<obj_t> obj{pool.acquire(), d};

值得注意的是,资源获取 总是 与其销毁配对。 在这个模型下你的问题不存在

std::weak_ptr<obj_t> b = obj;
obj = nullptr;  // or let obj get destroyed in any other way

if(auto c = b.lock())
    // doesn't happen