马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
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 的精确利用场景是那些资源如果大概就利用,如果不可利用则不消的场景,它不加入资源的生命周期管理。比方,网络分层结构中,Session 对象(会话对象)利用 Connection 对象(毗连对象)提供的服务工作,但是 Session 对象不管理 Connection 对象的生命周期,Session 管理 Connection 的生命周期是不公道的,由于网络底层堕落会导致 Connection 对象被烧毁,此时 Session 对象如果强行持有 Connection 对象与毕竟抵牾。
- std::weak_ptr 重要有两个用途:
它只能共同std::shared_ptr利用,不能单独利用。
- 防止 std::shared_ptr循环引用
如果两个std::shared_ptr相互引用,那么就会形成一个环,引用计数无法变成0,也会导致内存走漏。
- class Foo : public std::enable_shared_from_this<Foo> {
- public:
- Foo(){ std::cout<<"ctor\n"; }
- ~Foo(){ std::cout<<"dtor\n"; }
- void self()
- {
- fptr_ = shared_from_this();
- }
- private:
- std::shared_ptr<Foo> fptr_; // 改 fptr_ 为 std::weak_ptr 类型即可
- };
- int main() {
- {
- std::shared_ptr<Foo> fptr = std::make_shared<Foo>();
- fptr->self();
- }
- return 0;
- }
复制代码
- std::enable_shared_from_this<T>::shared_from_this
这是个侵入式计划。为的办理传入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,那么永久也无法析构。
- 为什么不直接传回this
std::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参数来构造自己。
智能指针标题
- share_ptr 与unique_ptr区别
重要在于前者接纳引用技能实现对象共享,redis里的对象管理也是接纳这个。而后者只能独占,不能赋值/复制,只能移动,由于其拷贝构造函数和赋值函数被禁用了。
在std::unique_ptr内部:
- // Disable copy from lvalue.
- unique_ptr(const unique_ptr&) = delete;
- unique_ptr& operator=(const unique_ptr&) = delete;
复制代码 参考
shared_ptr 指向一个动态数组须要注意什么?
析构器须要设置为 delete[]。而uniqued_ptr的的默认析构器模板类std::default_delete,能自动设别new int和new int[]由于不消担心。
- template< class Y > explicit shared_ptr( Y* ptr );
- template< class Y, class Deleter > shared_ptr( Y* ptr, Deleter d )
复制代码 上面一个,默认的析构器是delete ptr。当 Y* ptr = new Y[x],析构器也须要重置。
- #include <memory>
- #include <vector>
- #include <algorithm>
-
- int main() {
- // {
- // std::shared_ptr<int> shared_bad(new int[10]);
- // } // 析构函数调用 delete ,未定义行为
-
- {
- std::shared_ptr<int> shared_good(new int[10], std::default_delete<int[]>());
- } // 析构函数调用 delete[] , ok
-
- {
- std::unique_ptr<int> ptr(new int(5));
- } // unique_ptr<int> 使用 default_delete<int>
-
- {
- std::unique_ptr<int[]> ptr(new int[10]);
- } // unique_ptr<int[]> 使用 default_delete<int[]>
- }
复制代码 std::shared_ptr 线程安全 ?
std::shared_ptr的引用计数自己是安全且无锁的,但对象的读写则不是。也就是说std::shared_ptr对象的创建析构是线程安全的,但是多线程读写std::shared_ptr对象不是线程安全的。std::shared_ptr 内存是由于两个构成部门: 指向管理对象的指针 和 引用计数器。在读/写时,是直接对两个变量利用,不大概是原子范例的。由于 std::shared_ptr 有两个数据成员,读写利用不能原子化.使得多线程读写同一个 std::shared_ptr 对象须要加锁.
std::weak_ptr的实现原理
std::weak_ptr 是为了办理 std::shared_ptr 循环引用而生,构造 std::weak_ptr 对象只能通过 std::shared_ptr 来构造,但是std::weak_ptr 对象的生命周期对相应的 std::shared_ptr的引用计数不产生影响,即不增长大概镌汰引用计数。
std::weak_ptr的引用计数部门也是有锁利用,因此 std::weak_ptr 对象生命周期的构造与烧毁都是线程安全的。
- // 基类
- template<typename _Tp, _Lock_policy _Lp>
- class __weak_ptr
- {
- template<typename _Yp, typename _Res = void>
- using _Compatible = typename enable_if<__sp_compatible_with<_Yp*, _Tp*>::value, _Res>::type;
- // Constraint for assignment from shared_ptr and weak_ptr:
- template<typename _Yp>
- using _Assignable = _Compatible<_Yp, __weak_ptr&>;
- public:
- using element_type = typename remove_extent<_Tp>::type;
- constexpr __weak_ptr() noexcept
- : _M_ptr(nullptr), _M_refcount()
- { }
- __weak_ptr(const __weak_ptr&) noexcept = default;
- ~__weak_ptr() = default;
- // The "obvious" converting constructor implementation:
- //
- // template<typename _Tp1>
- // __weak_ptr(const __weak_ptr<_Tp1, _Lp>& __r)
- // : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) // never throws
- // { }
- //
- // has a serious problem.
- //
- // __r._M_ptr may already have been invalidated. The _M_ptr(__r._M_ptr)
- // conversion may require access to *__r._M_ptr (virtual inheritance).
- //
- // It is not possible to avoid spurious access violations since
- // in multithreaded programs __r._M_ptr may be invalidated at any point.
- template<typename _Yp, typename = _Compatible<_Yp>>
- __weak_ptr(const __weak_ptr<_Yp, _Lp>& __r) noexcept
- : _M_refcount(__r._M_refcount)
- { _M_ptr = __r.lock().get(); }
- template<typename _Yp, typename = _Compatible<_Yp>>
- __weak_ptr(const __shared_ptr<_Yp, _Lp>& __r) noexcept
- : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount)
- { }
- __weak_ptr(__weak_ptr&& __r) noexcept
- : _M_ptr(__r._M_ptr), _M_refcount(std::move(__r._M_refcount))
- { __r._M_ptr = nullptr; }
- template<typename _Yp, typename = _Compatible<_Yp>>
- __weak_ptr(__weak_ptr<_Yp, _Lp>&& __r) noexcept
- : _M_ptr(__r.lock().get()), _M_refcount(std::move(__r._M_refcount))
- { __r._M_ptr = nullptr; }
- __weak_ptr&
- operator=(const __weak_ptr& __r) noexcept = default;
- template<typename _Yp>
- _Assignable<_Yp>
- operator=(const __weak_ptr<_Yp, _Lp>& __r) noexcept
- {
- _M_ptr = __r.lock().get();
- _M_refcount = __r._M_refcount;
- return *this;
- }
- template<typename _Yp>
- _Assignable<_Yp>
- operator=(const __shared_ptr<_Yp, _Lp>& __r) noexcept
- {
- _M_ptr = __r._M_ptr;
- _M_refcount = __r._M_refcount;
- return *this;
- }
- __weak_ptr&
- operator=(__weak_ptr&& __r) noexcept
- {
- _M_ptr = __r._M_ptr;
- _M_refcount = std::move(__r._M_refcount);
- __r._M_ptr = nullptr;
- return *this;
- }
- template<typename _Yp>
- _Assignable<_Yp>
- operator=(__weak_ptr<_Yp, _Lp>&& __r) noexcept
- {
- _M_ptr = __r.lock().get();
- _M_refcount = std::move(__r._M_refcount);
- __r._M_ptr = nullptr;
- return *this;
- }
- __shared_ptr<_Tp, _Lp> lock() const noexcept
- { return __shared_ptr<element_type, _Lp>(*this, std::nothrow); }
- long use_count() const noexcept
- { return _M_refcount._M_get_use_count(); }
- bool expired() const noexcept
- { return _M_refcount._M_get_use_count() == 0; }
- template<typename _Tp1>
- bool owner_before(const __shared_ptr<_Tp1, _Lp>& __rhs) const noexcept
- { return _M_refcount._M_less(__rhs._M_refcount); }
- template<typename _Tp1>
- bool owner_before(const __weak_ptr<_Tp1, _Lp>& __rhs) const noexcept
- { return _M_refcount._M_less(__rhs._M_refcount); }
- void reset() noexcept
- { __weak_ptr().swap(*this); }
- void swap(__weak_ptr& __s) noexcept
- {
- std::swap(_M_ptr, __s._M_ptr);
- _M_refcount._M_swap(__s._M_refcount);
- }
- private:
- // Used by __enable_shared_from_this.
- void _M_assign(_Tp* __ptr, const __shared_count<_Lp>& __refcount) noexcept
- {
- if (use_count() == 0)
- {
- _M_ptr = __ptr;
- _M_refcount = __refcount;
- }
- }
- template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;
- template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;
- friend class __enable_shared_from_this<_Tp, _Lp>;
- friend class enable_shared_from_this<_Tp>;
- element_type* _M_ptr; // Contained pointer.
- __weak_count<_Lp> _M_refcount; // Reference counter.
- };
- /**
- * @brief A smart pointer with weak semantics.
- *
- * With forwarding constructors and assignment operators.
- */
- template<typename _Tp>
- class weak_ptr : public __weak_ptr<_Tp>
- {
- template<typename _Arg>
- using _Constructible = typename enable_if<is_constructible<__weak_ptr<_Tp>, _Arg>::value>::type;
- template<typename _Arg>
- using _Assignable = typename enable_if<is_assignable<__weak_ptr<_Tp>&, _Arg>::value, weak_ptr&>::type;
- public:
- constexpr weak_ptr() noexcept = default;
- template<typename _Yp,
- typename = _Constructible<const shared_ptr<_Yp>&>>
- weak_ptr(const shared_ptr<_Yp>& __r) noexcept
- : __weak_ptr<_Tp>(__r) { }
- weak_ptr(const weak_ptr&) noexcept = default;
- template<typename _Yp, typename = _Constructible<const weak_ptr<_Yp>&>>
- weak_ptr(const weak_ptr<_Yp>& __r) noexcept
- : __weak_ptr<_Tp>(__r) { }
- weak_ptr(weak_ptr&&) noexcept = default;
- template<typename _Yp, typename = _Constructible<weak_ptr<_Yp>>>
- weak_ptr(weak_ptr<_Yp>&& __r) noexcept
- : __weak_ptr<_Tp>(std::move(__r)) { }
- weak_ptr&
- operator=(const weak_ptr& __r) noexcept = default;
- template<typename _Yp>
- _Assignable<const weak_ptr<_Yp>&>
- operator=(const weak_ptr<_Yp>& __r) noexcept
- {
- this->__weak_ptr<_Tp>::operator=(__r);
- return *this;
- }
- template<typename _Yp>
- _Assignable<const shared_ptr<_Yp>&>
- operator=(const shared_ptr<_Yp>& __r) noexcept
- {
- this->__weak_ptr<_Tp>::operator=(__r);
- return *this;
- }
- weak_ptr&
- operator=(weak_ptr&& __r) noexcept = default;
- template<typename _Yp>
- _Assignable<weak_ptr<_Yp>>
- operator=(weak_ptr<_Yp>&& __r) noexcept
- {
- this->__weak_ptr<_Tp>::operator=(std::move(__r));
- return *this;
- }
- shared_ptr<_Tp> lock() const noexcept
- { return shared_ptr<_Tp>(*this, std::nothrow); }
- };
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!qidao123.com:ToB企服之家,中国第一个企服评测及软件市场,开放入驻,技术点评得现金 |