我可以在不删除对象的情况下重置shared_ptr吗?这样weak_ptr就失去了对它的引用



我想重置一个shared_ptr而不删除它的对象,让它的weak_ptr失去对它的引用。但是,由于某些原因,shared_ptr没有release((成员函数,所以我不能直接执行。最简单的解决方案是调用weak_ptr的reset((,但拥有shared_ptr并想要释放它的类不知道哪个类有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
}

背景

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

我可以创建一个管理器类来跟踪哪个弱指针指向哪个共享指针,但我想知道这是否可以通过其他方法解决。

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

您可以使用带有自定义deleter的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;

相关内容

  • 没有找到相关文章

最新更新