我开始研究c++ 11的智能指针,我没有看到std::weak_ptr有任何有用的用途。有人能告诉我什么时候std::weak_ptr是有用的/必要的吗?
当前回答
共享指针有一个缺点: Shared_pointer不能处理父子周期依赖关系。如果父类使用父类的对象使用共享指针,则表示在同一文件中,如果子类使用父类的对象。共享指针将无法析构所有对象,甚至在循环依赖场景中共享指针根本不调用析构函数。基本上共享指针不支持引用计数机制。
我们可以使用weak_pointer来克服这个缺点。
其他回答
受到@offirmo回复的启发,我写了这段代码,然后运行visual studio诊断工具:
#include <iostream>
#include <vector>
#include <memory>
using namespace std;
struct Member;
struct Team;
struct Member {
int x = 0;
Member(int xArg) {
x = xArg;
}
shared_ptr<Team> teamPointer;
};
struct Team {
vector<shared_ptr<Member>> members;
};
void foo() {
auto t1 = make_shared<Team>();
for (int i = 0; i < 1000000; i++) {
t1->members.push_back(make_shared<Member>(i));
t1->members.back()->teamPointer = t1;
}
}
int main() {
foo();
while (1);
return 0;
}
当指向团队的成员指针是shared_ptr teamPointer时,在foo()完成后内存就没有空闲了,即它停留在150mb左右。
但是如果在诊断工具中将其更改为weak_ptr teamPointer,您将看到一个峰值,然后内存使用量恢复到大约2MB。
缓存就是一个很好的例子。
对于最近访问的对象,您希望将它们保存在内存中,因此可以保留一个指向它们的强指针。定期扫描缓存,确定最近没有访问哪些对象。你不需要把它们保存在内存中,所以你去掉强指针。
但是,如果该对象正在使用,而其他一些代码持有指向它的强指针,该怎么办?如果缓存删除了指向该对象的唯一指针,就再也找不到它了。因此,缓存保留了一个弱指针,指向它需要找到的对象,如果它们碰巧留在内存中。
这正是弱指针所做的——它允许你在一个对象仍然在附近时定位它,但如果没有其他东西需要它,它就不会保留它。
共享指针有一个缺点: Shared_pointer不能处理父子周期依赖关系。如果父类使用父类的对象使用共享指针,则表示在同一文件中,如果子类使用父类的对象。共享指针将无法析构所有对象,甚至在循环依赖场景中共享指针根本不调用析构函数。基本上共享指针不支持引用计数机制。
我们可以使用weak_pointer来克服这个缺点。
Shared_ptr:保存真实对象。
weak_ptr:使用lock连接到真正的所有者,否则返回NULL shared_ptr。
大致来说,weak_ptr角色类似于房屋中介的角色。如果没有中介,要想租到房子,我们可能得在城里随机找房子。中介会确保我们只去那些还能租到的房子。
Here's one example, given to me by @jleahy: Suppose you have a collection of tasks, executed asynchronously, and managed by an std::shared_ptr<Task>. You may want to do something with those tasks periodically, so a timer event may traverse a std::vector<std::weak_ptr<Task>> and give the tasks something to do. However, simultaneously a task may have concurrently decided that it is no longer needed and die. The timer can thus check whether the task is still alive by making a shared pointer from the weak pointer and using that shared pointer, provided it isn't null.
推荐文章
- Shared_ptr转换为数组:应该使用它吗?
- c++ 11中的递归lambda函数
- c++ auto关键字。为什么它是魔法?
- Std::auto_ptr改为Std::unique_ptr
- 什么是“参数依赖查找”(又名ADL,或“Koenig查找”)?
- 公共朋友交换成员函数
- 下面这些短语在c++中是什么意思:0 -,default-和value-initialization?
- 现代c++能让你免费获得性能吗?
- c++11返回值优化或移动?
- 函数标题中的箭头操作符(->)
- c++中“using”关键字背后的逻辑是什么?
- 我如何类型定义一个函数指针与c++ 11使用语法?
- cbegin/cend背后的原因是什么?
- 如何在Eclipse CDT中启用c++ 11/ c++ 0x支持?
- 如何停止c++控制台应用程序从退出立即?