我可以在不删除对象的情况下重置 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_ptr
和std::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
我想在不删除其对象的情况下重置 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_ptr
和std::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