我知道shared_ptr是如何工作的,但weak_ptr的作用还不太清楚。我知道它可以在引用计数不为零时检测循环引用,但除此之外,我不太明白它是如何做到这一点的。它具体是做什么呢?
我知道shared_ptr是如何工作的,但weak_ptr的作用还不太清楚。我知道它可以在引用计数不为零时检测循环引用,但除此之外,我不太明白它是如何做到这一点的。它具体是做什么呢?
#include <vector>
#include <memory>
#include <ostream>
int main()
{
// Fill container with values 1-50. This container OWNS these values.
std::vector<std::shared_ptr<int>> owning_container;
for(int i = 1; i <= 50; ++i)
{
owning_container.emplace_back(std::make_shared<int>(i));
}
// Create a sepearate container that references all owned values that are multiples of 5.
std::vector<std::weak_ptr<int>> referencing_container;
for(std::shared_ptr<int> const& i : owning_container)
{
if((*i) % 5 == 0)
{
// Make weak_ptr that references shared_ptr
referencing_container.emplace_back(i);
}
}
// Go through the owned values and delete all that are multiples of 10.
for(auto it = owning_container.begin(); it != owning_container.end();)
{
std::shared_ptr<int> const& i = *it;
if(*i % 10 == 0)
{
it = owning_container.erase(it);
}
else
{
++it;
}
}
// Now go through the referencing container and print out all values.
// If we were dealing with raw pointers in both containers here we would access deleted memory,
// since some of the the actual resources (in owning_container) that referencing_container
// references have been removed.
for(std::weak_ptr<int> const& i_ref : referencing_container)
{
// Check if the shared resource still exists before using it (purpose of weak_ptr)
std::shared_ptr<int> i = i_ref.lock();
if(i)
{
std::cout << *i << std::endl;
}
}
return 0;
}
shared_ptr
),另一个容器需要引用它们 (weak_ptr
)。引用并不拥有这个资源,只需要在需要时访问它(如果存在)。为了检查被引用的资源是否仍然存在,我们使用weak_ptr::lock()
将weak_ptr
转换为shared_ptr
。那些仍然存在的资源将会返回一个有效的shared_ptr
,而那些不存在的资源将返回一个空的shared_ptr
。我们可以使用shared_ptr
的operator bool()
来检查它是否为null,然后再使用它。
一个更简单的场景可能是,假设你正在制作一个游戏,游戏中的每个对象都由一个game_object
表示。比如说你有一个寻找逻辑用于向敌人寻找目标game_object
。使用以上方法,你可以让敌人持有一个weak_ptr<game_object>
。它并没有拥有这个game_object
,如果其他东西杀死了它的目标,它的目标应该死亡,而不是停留在某种悬空状态。如果敌人的目标仍然存在的话(它可以通过锁定weak_ptr
来检查),则可以执行寻找逻辑;否则,它可以寻找一个新的目标。这个game_object
的"所有者"可以是某种game_world
类 - 它将拥有一个shared_ptr<game_object>
容器。当敌人需要一个新的目标时,它可以搜索这个容器,并从game_world
的shared_ptr
创建它的weak_ptr
。
weak_ptr::lock()
方法),它们不允许您以任何方式操作资源。我的意见是,现实生活中最常见的需要这种行为的情况是循环依赖和(较少)缓存。