图片来自
std::enable_shared_from_this 有什么意义? - 孔洽孔洽的回答 - 知乎
https://www.zhihu.com/question/30957800/answer/2700292012
答案参考一下,应该不完全对
当指向对象的std::shared_ptr一创建,被管理对象的控制块就建立了。
被管理的对象的控制块中有引用计数(reference count),当引用计数为0时,被管理的对象会被销毁。
控制块的创建会遵循下面几条规则:
std::make_shared会创建控制块
从 std::unique_ptr 上构造出 std::shared_ptr的时候,会创建控制块
从原始指针上构造 std::shared_ptr的时候会创建控制块
假若我们为一个指针构建了多个控制块,那么会有多个引用计数,意味着对象可能销毁多次,这是非法行为
多次从原始指针上构建智能指针,实际存在多个互不相干的引用计数,大家都为1,然后一旦有一个智能指针不再指向该对象,引用为0就会析构对象,就会出错
weak_ptr 一般者是通过 shared _ptr 来创建的,两者就指向了相同位置
weak_ptr不会改变资源的引用计数,只是一个观察者的角色,通过观察shared_ptr来判定资源是否存在,不会影响指向对象的生命周期,而shared_ptr引用计数为0则会析构对象
weak_ptr持有的引用计数,不是资源的引用计数,而是同一个资源的观察者的计数
weak_ptr没有提供常用的指针操作,无法直接访问资源,需要先通过lock方法提升为shared_ptr强智能指针,才能访问资源
成员函数use_count() 观测资源引用计数
成员函数expired() 功能相当于 use_count()为 0 表示被观测的资源(也就是shared_ptr的管理的资源)被销毁
成员函数lock()从被观测的shared_ptr获得一个可用的shared_ptr对象, 进而操作资源。但当expired()==true的时候,lock()函数将返回一个存储空指针的shared_ptr
来自csdn
原文链接:https://blog.csdn.net/qq_53111905/article/details/122240842
shared_from_this要解决的问题
需求: 在类的内部需要自身的shared_ptr 而不是this裸指针,直接从this指针创建?那会导致出现多个引用计数器,会错误析构,因为每调用一次就创建一个指针
场景: 在类中发起一个异步操作, callback回来要保证发起操作的对象仍然有效,std::bind函数和对象,结果对象先被析构了,那还调用个屁
异步回调的时候对象可能已经被销毁了 所以使用shared_ptr 传出去就是保证最少还有一个引用计数维持对象的生命周期直到回调结束
struct A {
void func() {
std::shared_ptr<A> local_sp_a(this);
// do something with local_sp_a
}
};
上面这段代码,由成员函数直接在this上构建智能指针,当离开该函数作用域,local_sp_a就会失效,则引用计数少1,则会立即析构this
改成这样
struct A : public enable_shared_from_this {
void func() {
std::shared_ptr<A> local_sp_a = shared_from_this();
// do something with local_sp
}
};
shared_from_this()会查找当前对象控制块,然后创建一个新的std::shared_ptr关联这个控制块。
用这个函数之前,是假设当前对象已经存在一个关联的控制块。因此,必须已经存在一个指向当前对象的std::shared_ptr。
如果没有std::shared_ptr指向当前对象(即当前对象没有关联控制块),那么shared_from_this会抛出一个异常。
智能指针的应用场景其实大概就了解了,
有时候,对象已经不存在了,被析构了,然而程序仍在调用该对象的成员函数,则会出错
异步,以及多线程的情况下,都会出现对象可能不存在了的情况
可以通过weak_ptr的lock方法判断是否为nullptr来判断对象是否被析构