开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第6天,点击查看活动详情
【C++新特性】智能指针
std::weak_ptr
std::weak_ptr是一种弱引用,它不能单独使用,设计之初是为了配合std::shared_ptr,解决后者的问题。
-
使用注意:
- 不能直接指向原始指针:
std::weak_ptr<int> wp (new int); - 只能指向
std::shared_ptr对象或者std::weak_ptr对象 - 不增加引用计数
- 可以用
expired()来检测指向的std::shared_ptr管理的对象是否被析构了。 - 不能直接使用
std::shared_ptr管理的对象,如果要使用需要调用lock()。如果底层的对象还没被析构,那么就会返回一个std::shared_ptr指针,指向该对象,否则返回nullptr。
- 不能直接指向原始指针:
-
构造函数
constexpr weak_ptr() noexcept; weak_ptr( const weak_ptr& r ) noexcept; weak_ptr( weak_ptr&& r ) noexcept; template< typename Y > weak_ptr( const weak_ptr<Y>& r ) noexcept; template< typename Y > weak_ptr( weak_ptr<Y>&& r ) noexcept; template< typename Y > weak_ptr( const std::shared_ptr<Y>& r ) noexcept;从构造函数可见,
std::weak_ptr只能接受std::weak_ptr和std::shared_ptr类型,而不能std::weak_ptr<T> wp (new T);。移动语义下的构造函数,构造完成
r将会变成nullptr,不可用。 -
函数
-
std::weak_ptr主要有两个用途: 它只能配合std::shared_ptr使用,不能单独使用。-
防止
std::shared_ptr循环引用 如果两个std::shared_ptr相互引用,那么就会形成一个环,引用计数无法变成0,也会导致内存泄漏。 -
std::enable_shared_from_this<T>::shared_from_this什么情况下需要使用 *shared_from_this()*??? 用于返回当前对象*this的std::shared_ptr类型指针时:class Foo : public enable_shared_from_this<Foo>{ public: Foo(){ std::cout<<"Foo ctor.\n"; } ~Foo(){ std::cout<<"Foo dtor.\n"; } std::shared_ptr<Foo> getSelf(){ return shared_from_this(); } }; int main() { Foo* foo = new Foo; std::shared_ptr<Foo> sp1(foo); std::shared_ptr<Foo> sp2 = sp1->getSelf(); // 为了对 foo对象进行共享 std::cout<<std::boolalpha; std::cout<<(sp2.get()== foo)<<std::endl; std::cout<<sp1.use_count()<<std::endl; }函数原型
template<typename _Tp> class enable_shared_from_this { protected: ... public: shared_ptr<_Tp> shared_from_this() { return shared_ptr<_Tp>(this->_M_weak_this); } shared_ptr<const _Tp> shared_from_this() const { return shared_ptr<const _Tp>(this->_M_weak_this); } private: ... mutable weak_ptr<_Tp> _M_weak_this; }enable_shared_from_this的子类需要返回自身的std::shared_ptr指针,那么就需要继承这个类。-
成员变量为什么是
weak_ptr类型 因为如果是std::shared_ptr类型,那么就永远无法析构对象自身。这个
_M_weak_this不是这个类中初始化,而是在shared_ptr中初始化,初始化的值就是this。因此如果智能指针类型是std::shared_ptr,那么这个类对象一旦创建,引用计数就是1,那么永远也无法析构。 -
为什么不直接传回
thisstd::shared_ptr的引用计数增加是需要用operator=实现的。class Foo {/** ... */}; int main() { Foo* foo = new Foo; std::shared_ptr<Foo> sp1(foo); std::shared_ptr<Foo> sp2(foo); std::cout<<sp1.use_count()<<std::endl; // 输出是1 }也就是说,尽管
sp1和sp2都指向了foo,但是却不共享计数,当析构的时候就会被析构两次,产生未定义行为。std::weak_ptr可以接受std::shared_ptr参数来构造自己,std::shared_ptr也具有接受std::weak_ptr参数来构造自己。
-
-