一、auto_ptr(C++98内容,C++11开始被舍弃)
先上源码(位于memory.h中):
template<class _Ty>
class auto_ptr
{ // wrap an object pointer to ensure destruction
public:
typedef _Ty element_type;
explicit auto_ptr(_Ty * _Ptr = nullptr) noexcept
: _Myptr(_Ptr)
{ // construct from object pointer
}
auto_ptr(auto_ptr& _Right) noexcept
: _Myptr(_Right.release())
{ // construct by assuming pointer from _Right auto_ptr
}
auto_ptr(auto_ptr_ref<_Ty> _Right) noexcept
{ // construct by assuming pointer from _Right auto_ptr_ref
_Ty * _Ptr = _Right._Ref;
_Right._Ref = nullptr; // release old
_Myptr = _Ptr; // reset this
}
template<class _Other>
operator auto_ptr<_Other>() noexcept
{ // convert to compatible auto_ptr
return (auto_ptr<_Other>(*this));
}
template<class _Other>
operator auto_ptr_ref<_Other>() noexcept
{ // convert to compatible auto_ptr_ref
_Other * _Cvtptr = _Myptr; // test implicit conversion
auto_ptr_ref<_Other> _Ans(_Cvtptr);
_Myptr = nullptr; // pass ownership to auto_ptr_ref
return (_Ans);
}
template<class _Other>
auto_ptr& operator=(auto_ptr<_Other>& _Right) noexcept
{ // assign compatible _Right (assume pointer)
reset(_Right.release());
return (*this);
}
template<class _Other>
auto_ptr(auto_ptr<_Other>& _Right) noexcept
: _Myptr(_Right.release())
{ // construct by assuming pointer from _Right
}
auto_ptr& operator=(auto_ptr& _Right) noexcept
{ // assign compatible _Right (assume pointer)
reset(_Right.release());
return (*this);
}
auto_ptr& operator=(auto_ptr_ref<_Ty> _Right) noexcept
{ // assign compatible _Right._Ref (assume pointer)
_Ty * _Ptr = _Right._Ref;
_Right._Ref = 0; // release old
reset(_Ptr); // set new
return (*this);
}
~auto_ptr() noexcept
{ // destroy the object
delete _Myptr;
}
_NODISCARD _Ty& operator*() const noexcept
{ // return designated value
#if _ITERATOR_DEBUG_LEVEL == 2
_STL_VERIFY(_Myptr, "auto_ptr not dereferencable");
#endif /* _ITERATOR_DEBUG_LEVEL == 2 */
return (*get());
}
_NODISCARD _Ty * operator->() const noexcept
{ // return pointer to class object
#if _ITERATOR_DEBUG_LEVEL == 2
_STL_VERIFY(_Myptr, "auto_ptr not dereferencable");
#endif /* _ITERATOR_DEBUG_LEVEL == 2 */
return (get());
}
_NODISCARD _Ty * get() const noexcept
{ // return wrapped pointer
return (_Myptr);
}
_Ty * release() noexcept
{ // return wrapped pointer and give up ownership
_Ty * _Tmp = _Myptr;
_Myptr = nullptr;
return (_Tmp);
}
void reset(_Ty * _Ptr = nullptr)
{ // destroy designated object and store new pointer
if (_Ptr != _Myptr)
delete _Myptr;
_Myptr = _Ptr;
}
private:
_Ty * _Myptr; // the wrapped object pointer
};
1.接口简介
接口 | 作用 |
auto_ptr(_Ty * _Ptr) | 构造函数。创建一个auto_ptr对象,并管理指针_Ptr的释放 |
~auto_ptr() | 析构函数。释放管理的指针_Myptr |
operator*() | 重载*操作符获取当前 auto_ptr 指针指向的数据。 |
operator->() | 重载 ->操作符,当智能指针指向非基础类型时,通过 -> 运算符可以获取其内部的指定成员。 |
operator=() | 重载 = 操作符,从而将一个相同类型指针的auto_ptr赋值给当前auto_ptr,当前auto_ptr获得指针的所有权。 |
get() | 获取当前 auto_ptr 指针内部包含的普通指针。 |
release() | 释放当前 auto_ptr 指针对所指堆内存的所有权(注意不是释放内存),并返回指针。 |
reset(p) | 如果p不等于当前auto_ptr管理的指针,则释放当前管理的指针,并开始管理;否则直接赋值。 |
2.成员
可以看到auto_ptr是一个类模板,整体结构比较简单,只有一个成员(被包装的指针):
_Ty * _Myptr;
3.构造/析构
explicit auto_ptr(_Ty * _Ptr = nullptr) noexcept
: _Myptr(_Ptr)
{ // construct from object pointer
}
~auto_ptr() noexcept
{ // destroy the object
delete _Myptr;
}
构造函数负责将参数_Ptr给成员_Myptr初始化。
析构函数负责释放成员_Myptr。
4.操作接口
_Ty * release() noexcept
{ // return wrapped pointer and give up ownership
_Ty * _Tmp = _Myptr;
_Myptr = nullptr;
return (_Tmp);
}
void reset(_Ty * _Ptr = nullptr)
{ // destroy designated object and store new pointer
if (_Ptr != _Myptr)
delete _Myptr;
_Myptr = _Ptr;
}
auto_ptr提供release和reset两个接口
release会将当前管理的内存返回,并将_Myptr置空。注意不是释放当前内存
reset则根据传入的参数决定行为,如果传入的指针不是当前保存的指针,则会释放当前指向的内存,并重新赋值
5.访问接口
_NODISCARD _Ty& operator*() const noexcept
{ // return designated value
#if _ITERATOR_DEBUG_LEVEL == 2
_STL_VERIFY(_Myptr, "auto_ptr not dereferencable");
#endif /* _ITERATOR_DEBUG_LEVEL == 2 */
return (*get());
}
_NODISCARD _Ty * operator->() const noexcept
{ // return pointer to class object
#if _ITERATOR_DEBUG_LEVEL == 2
_STL_VERIFY(_Myptr, "auto_ptr not dereferencable");
#endif /* _ITERATOR_DEBUG_LEVEL == 2 */
return (get());
}
_NODISCARD _Ty * get() const noexcept
{ // return wrapped pointer
return (_Myptr);
}
重载*操作符,返回指针指向的数据
重载->操作符,返回顶层指针,可以通过此指针访问原始指针的内容,但是不能修改该指针的指向。
get()函数,与重载->操作符一致。(源码可以看到就是调用的get()函数)
6.拷贝/赋值
auto_ptr(auto_ptr& _Right) noexcept
: _Myptr(_Right.release())
{ // construct by assuming pointer from _Right auto_ptr
}
auto_ptr& operator=(auto_ptr& _Right) noexcept
{ // assign compatible _Right (assume pointer)
reset(_Right.release());
return (*this);
}
auto_ptr重载了拷贝和赋值函数,以此实现所有权的变化。
两者主要操作都是调用了release函数,释放被拷贝智能指针的所有权并置空,将其转到当前智能指针下。
using namespace std;
int main()
{
//构造
auto_ptr<int> iptr(new int(10));
auto_ptr<string> sptr(new string("123"));
//release之后auto_ptr中的指针置空
int *ival = iptr.release();
string *sval = sptr.release();
cout << *ival <<" "<< sval->c_str() << endl; //10 "123"
//get获取原始指针
int *ival2 = iptr.get();
string *sval2 = sptr.get();
cout << (ival2 ==nullptr) << " " << (sval2==nullptr) << endl; //true
//reset将参数赋值给auto_ptr中管理的指针
iptr.reset(ival);
sptr.reset(sval);
cout << *ival << " " << sval->c_str() << endl; //10 "123"
}
7.auto_ptr的问题
- 因为指针所有权会随着赋值、拷贝等操作变化,导致原有的auto_ptr失效,因此很容易引起崩溃。这就使得在一些很常见的场景下出现问题:
using namespace std;
void test(auto_ptr<int> val) {
}
int main()
{
auto_ptr<int> iptr(new int(10));
test(iptr); //iptr对指针的所有权被释放,后续访问崩溃
cout << *iptr << endl; //10 "123"
}
这里的根本原因其实就是忽略了,指针拷贝的场景。
- 由于没有重载bool操作符,因此对指针是否失效智能通过get函数返回后比较,十分不便。
二、unique_ptr
1.简介
以独占的方式管理内存,为了避免auto_ptr的拷贝问题,一方面删除了拷贝构造和拷贝赋值
unique_ptr(const unique_ptr&) = delete;
unique_ptr& operator=(const unique_ptr&) = delete;
另一方面提供了移动拷贝构造和移动赋值
unique_ptr(unique_ptr&& _Right) noexcept
: _Mybase(_Right.release(),
_STD forward<_Dx>(_Right.get_deleter()))
{ // construct by moving _Right
}
unique_ptr& operator=(unique_ptr&& _Right) noexcept
{ // assign by moving _Right
if (this != _STD addressof(_Right))
{ // different, do the move
reset(_Right.release());
this->get_deleter() = _STD forward<_Dx>(_Right.get_deleter());
}
return (*this);
}
以适应移动语义:
unique_ptr<int> test()
{
return unique_ptr<int>(new int(10));
}
int main()
{
//构造
unique_ptr<int> iptr(new int(11));
unique_ptr<int> iptr2(std::move(iptr));
unique_ptr<int> iptr3 = test(); //返回值时的移动语义
unique_ptr<int> iptr4 = std::move(iptr3); //通过move调用移动语义
2.接口简介
成员函数名 | 功 能 |
operator*() | 获取当前 unique_ptr 指针指向的数据。 |
operator->() | 重载 -> 运算符,当智能指针自定义类型时,通过 -> 运算符可以获取其内部的指定成员。 |
operator =() | 重载了 = 运算符,从而可以将 nullptr 或者一个右值 unique_ptr 指针直接赋值给当前同类型的 unique_ptr 指针。 |
operator []() | 重载了 [] 运算符,当 unique_ptr 指针指向一个数组时,可以直接通过 [] 获取指定下标位置处的数据。 |
get() | 获取当前 unique_ptr 指针内部包含的普通指针。 |
get_deleter() | 获取当前 unique_ptr 指针的删除器。 |
operator bool() | 重载bool运算符,判断unique_ptr的指针是否为空。 |
release() | 释放当前 unique_ptr 指针对所指堆内存的所有权,但该存储空间并不会被销毁。 |
reset(p) | 其中 p 表示一个普通指针,如果 p 为 nullptr,则当前 unique_ptr 也变成空指针;反之,则该函数会释放当前 unique_ptr 指针指向的堆内存(如果有),然后获取 p 所指堆内存的所有权(p 为 nullptr)。 |
swap(x) | 交换当前 unique_ptr 指针和同类型的 x 指针。 |
整体接口与auto_ptr功能类似。
3.类设计(vs2017版)
UML类图
unique_ptr
截取unique_ptr类模板部分源码:
// CLASS TEMPLATE unique_ptr SCALAR
template<class _Ty,
class _Dx> // = default_delete<_Ty>
class unique_ptr
: public _Unique_ptr_base<_Ty, _Dx>
{ // non-copyable pointer to an object
public:
//...
}
- 可以看到unique_ptr为类模板,接收两个类模板参数_Ty和_Dx,其中:
- _Ty表示所需管理的指针类型
- _Dx表示释放指针内存的删除器,默认采用default_delete<_Ty>方式,一般可以不传。
- 此外,unique_ptr中没有成员变量,而是存储与其基类_Unique_ptr_base中
default_delete<_Ty>
default_delete<_Ty>作为默认的删除器,源码如下:
template<class _Ty>
struct default_delete
{ // default deleter for unique_ptr
constexpr default_delete() noexcept = default;
template<class _Ty2,
enable_if_t<is_convertible_v<_Ty2 *, _Ty *>, int> = 0>
default_delete(const default_delete<_Ty2>&) noexcept
{ // construct from another default_delete
}
void operator()(_Ty * _Ptr) const noexcept
{ // delete a pointer
static_assert(0 < sizeof (_Ty),
"can't delete an incomplete type");
delete _Ptr;
}
};
可以看到主要接口为operator(),采用delete 释放内存。
_Unique_ptr_base
_Unique_ptr_base作为unique_ptr的基类,部分源码如下:
// CLASS TEMPLATE _Unique_ptr_base
template<class _Ty,
class _Dx>
class _Unique_ptr_base
{ // stores pointer and deleter
public:
typedef remove_reference_t<_Dx> _Dx_noref;
typedef typename _Get_deleter_pointer_type<_Ty, _Dx_noref>::type pointer;
//...
_Compressed_pair<_Dx, pointer> _Mypair;
};
可以看到,通过_Compressed_pair<_Dx, pointer> _Mypair;管理删除器和指针。而_Compressed_pair部分源码如下:
template<class _Ty1,
class _Ty2,
bool = is_empty_v<_Ty1> && !is_final_v<_Ty1>>
class _Compressed_pair final
: private _Ty1
{ // store a pair of values, deriving from empty first
private:
_Ty2 _Myval2;
using _Mybase = _Ty1; // for visualization
}
_Compressed_pair类通过继承自_Ty1(删除器),以达到当使用默认删除器时,通过EBO技术使得其不消耗额外的内存空间。详细来说就是:
如果不采用这种方式,那么必然在_Compressed_pair内部需要再添加一个变量持有删除器,那么_Compressed_pair的内存空间必然变成:
删除器内存空间(4)+指针空间(4)
而且即使我们使用默认的删除器也会如此,这样就比裸指针内存空间大。
而采用EBO的技术,则将_Compressed_pair继承自迭代器,由于默认删除器default_delete不包含非静态数据成员,因此空间为1,而通过EBO技术的优化,_Compressed_pair则会将这一个字节内存优化掉,因此只有:
指针空间(4)
的内存空间大小,与裸指针空间相同。
4.使用场景
首先,由于unique_ptr的独占性,因此比较适用于指针内容不会要求被共享的场景。
其次,由于添加了移动语义,且由于独占性导致移动后则有对方管理释放,因此在工厂函数中比较适合用unique_ptr返回创建的对象。
最后,对于传入删除器的场景,往往用于对象不需要/不允许释放,其他释放手段(如文件需要用fclose)等等场合。
三、shared_ptr
1.简介
- shared_ptr是一种保存指针但共享指针所有权的一种智能指针,即多个shared_ptr可能保存同一个指针(注意是通过赋值、拷贝构造,而不是用指针初始化多个shared_ptr)。
-
- 注意,如果一个指针多次使用shared_ptr构造保存,则会导致多次释放的问题。
- shared_ptr管理的指针在以下两种情况下会被释放:
-
- 管理指针的最后一个shared_ptr对象被释放
- 管理指针的最后一个shared_ptr对象调用reset(p)或operator=()时。
- shared_ptr也可以提供删除器,但是并不是作为类模板参数,而是构造函数的函数模板参数。
- shared_ptr的共享实例的任何操作都是线程同步的,但对于保存的指针的操作无法保证这一点。
2.接口简介
shared_ptr以通过计数的方式共享资源。
成员函数名 | 功 能 |
operator*() | 重载 * 运算符,获取当前保存指针指向的数据。 |
operator->() | 重载 -> 运算符,当智能指针为自定义类型时,通过 -> 运算符可以获取其内部的指定成员。 |
operator =() | 重载了 = 运算符,将计数成员和指针成员赋值给当前智能指针。 |
operator []() | 重载了 [] 运算符,当 shared_ptr 中指针指向一个数组时,可以直接通过 [] 获取指定下标位置处的数据。 |
get() | 获取当前 shared_ptr中 指针内部包含的原始指针。 |
use_count() | 返回共享的智能指针数,也就是这个原始指针被多少个shared_ptr共享。 |
operator bool() | 重载bool运算符,判断shared_ptr的指针是否为空。 |
reset([p]) | 重置存储的原始指针,如果不带参数,则表示当前shared_ptr置空,与之共享的shared_ptr的计数减1; |
swap(x) | 交换当前 shared_ptr 指针和同类型的 x 指针。 |
3.类设计
UML类图
shared_ptr
shared_ptr并没有任何数据成员(数据成员来自于基类_Ptr_base)。类声明如下:
template<class _Ty>
class shared_ptr
: public _Ptr_base<_Ty>
而其中大部分接口也都是间接调用基类_Ptr_base的接口,因此我们主要看一下_Ptr_base。
_Ptr_base
成员
基类拥有两个成员
element_type * _Ptr{nullptr};
_Ref_count_base * _Rep{nullptr};
前者_Ptr为保存的指针。而后者_Rep则是用于计数的指针(详细参考下面的_Ref_count_base)
拷贝
template<class _Ty2>
void _Copy_construct_from(const shared_ptr<_Ty2>& _Other)
{ // implement shared_ptr's (converting) copy ctor
if (_Other._Rep)
{
_Other._Rep->_Incref();
}
_Ptr = _Other._Ptr;
_Rep = _Other._Rep;
}
shared_ptr的拷贝操作都调用的基类_Copy_construct_from函数,从上面的源码可以看到实现也比较简单:
- 先调用被拷贝对象的Incref()函数,将计数+1;
- 然后再将被拷贝对象保存的指针和计数器拷贝给当前对象。
_Ref_count_base
成员
_Atomic_counter_t _Uses;
_Atomic_counter_t _Weaks;
- 计数器拥有两个数据成员分别用于shared_ptr和weak_ptr的计数(所以weak_ptr也是有计数滴)
- 而这两个数据成员都是_Atomic_counter_t类型,以此数据操作的线程安全。而shared_ptr向上也只有这两个数据成员,因此shared_ptr的所有操作都是线程安全的。
构造
_Ref_count_base()
: _Uses(1), _Weaks(1) // non-atomic initializations
{ // construct
}
构造时默认_Uses和_Weak都初始化为1
计数
void _Incref()
{ // increment use count
_MT_INCR(_Uses);
}
void _Incwref()
{ // increment weak reference count
_MT_INCR(_Weaks);
}
调用_MT_INCR对强计数和弱计数分别累加。_MT_INCR和下面的_MT_DECR都是平台相关的累加/减操作。
void _Decref()
{ // decrement use count
if (_MT_DECR(_Uses) == 0)
{ // destroy managed resource, decrement weak reference count
_Destroy();
_Decwref();
}
}
void _Decwref()
{ // decrement weak reference count
if (_MT_DECR(_Weaks) == 0)
{
_Delete_this();
}
}
- _Decref调用_MT_DECR对强计数-1,
- 并判断是否计数为0,如果是,则调用_Destroy删除器(_Ref_count_base下的_Destroy为纯虚函数,具体实现在子类中,主要也就是用于释放管理的指针)。
- 并调用_Decwref()。
- _Decwref调用_MT_DECR对强计数-1,
- 并判断是否计数为0,如果是,则调用_Delete_this(同_Destroy一样也为纯虚函数,子类中用于释放计数器本身)。
- 因此当use_count减为0时,管理的指针对象会被释放,但删除器并不一定会被立即释放,而是等弱引用计数清空,才会释放。
_Ref_count
template<class _Ty>
class _Ref_count
: public _Ref_count_base
{ // handle reference counting for pointer without deleter
public:
explicit _Ref_count(_Ty * _Px)
: _Ref_count_base(), _Ptr(_Px)
{ // construct
}
private:
virtual void _Destroy() noexcept override
{ // destroy managed resource
delete _Ptr;
}
virtual void _Delete_this() noexcept override
{ // destroy self
delete this;
}
_Ty * _Ptr;
};
计数器_Ref_count_base的子类,将保存的指针传入,并重写_Destroy和_Delete_this,实现释放操作。
_Ref_count_resource
// CLASS TEMPLATE _Ref_count_resource
template<class _Resource,
class _Dx>
class _Ref_count_resource
: public _Ref_count_base
{ // handle reference counting for object with deleter
public:
_Ref_count_resource(_Resource _Px, _Dx _Dt)
: _Ref_count_base(), _Mypair(_One_then_variadic_args_t(), _STD move(_Dt), _Px)
{ // construct
}
virtual void * _Get_deleter(const type_info& _Typeid) const noexcept override
{ // return address of deleter object
#if _HAS_STATIC_RTTI
if (_Typeid == typeid(_Dx))
{
return (const_cast<_Dx *>(_STD addressof(_Mypair._Get_first())));
}
#else /* _HAS_STATIC_RTTI */
(void)_Typeid;
#endif /* _HAS_STATIC_RTTI */
return (nullptr);
}
private:
virtual void _Destroy() noexcept override
{ // destroy managed resource
_Mypair._Get_first()(_Mypair._Get_second());
}
virtual void _Delete_this() noexcept override
{ // destroy self
delete this;
}
_Compressed_pair<_Dx, _Resource> _Mypair;
};
而对于资源类型,则实现了_Ref_count_resource传入删除器定制释放操作。其中_Ref_count_resource的数据成员又是_Compressed_pair。
_Ref_count_resource_alloc
// CLASS TEMPLATE _Ref_count_resource_alloc
template<class _Resource,
class _Dx,
class _Alloc>
class _Ref_count_resource_alloc
: public _Ref_count_base
{ // handle reference counting for object with deleter and allocator
public:
_Ref_count_resource_alloc(_Resource _Px, _Dx _Dt, const _Alloc& _Ax)
: _Ref_count_base(), _Mypair(_One_then_variadic_args_t(), _STD move(_Dt),
_One_then_variadic_args_t(), _Ax, _Px)
{ // construct
}
virtual void * _Get_deleter(const type_info& _Typeid) const noexcept override
{ // return address of deleter object
#if _HAS_STATIC_RTTI
if (_Typeid == typeid(_Dx))
{
return (const_cast<_Dx *>(_STD addressof(_Mypair._Get_first())));
}
#else /* _HAS_STATIC_RTTI */
(void)_Typeid;
#endif /* _HAS_STATIC_RTTI */
return (nullptr);
}
private:
using _Myalty = _Rebind_alloc_t<_Alloc, _Ref_count_resource_alloc>;
virtual void _Destroy() noexcept override
{ // destroy managed resource
_Mypair._Get_first()(_Mypair._Get_second()._Get_second());
}
virtual void _Delete_this() noexcept override
{ // destroy self
_Myalty _Al = _Mypair._Get_second()._Get_first();
allocator_traits<_Myalty>::destroy(_Al, this);
_Deallocate_plain(_Al, this);
}
_Compressed_pair<_Dx, _Compressed_pair<_Myalty, _Resource>> _Mypair;
};
对于第三个子类_Ref_count_resource_alloc,则是传入了删除器和分配器,用于资源的释放和分配。此外其数据成员为两层_Compressed_pair,因为删除器和分配器都有可能为空类,以此节省空类时的空间。
四、weak_ptr
1.简介
- weak_ptr以弱引用的方式持有指针,它并不拥有指针的所有权
- weak_ptr需要通过lock接口获取临时的shared_ptr才能访问指针。
- weak_ptr比较重要的一个作用是打破shared_ptr的环形引用问题。
2.接口简介
成员函数名 | 功 能 |
operator =() | 重载了 = 运算符,将计数成员和指针成员赋值给当前智能指针。 |
reset() | 没有参数。释放当前weak_ptr对象 |
use_count() | 返回共享的智能指针数,也就是这个原始指针被多少个shared_ptr共享。 |
expired() | 判断当前引用的对象(指针)是否被释放 |
lock() | 返回一个临时的shared_ptr,共享保存的指针。如果指针被释放,则返回一个空的shared_ptr |
3.类设计
weak_ptr
template<class _Ty>
class weak_ptr
: public _Ptr_base<_Ty>
weak_ptr和shared_ptr一样,继承自_Ptr_base,整体类结构与shared_ptr类似,只不过基于_Ptr_base封装了一些不同的构造和操作入口。
基类_Ptr_base中的计数器_Ref_count_base中的成员_Weaks用于weak_ptr的计数。
weak_ptr比较重要的两个函数是expired和lock:
_NODISCARD bool expired() const noexcept
{ // return true if resource no longer exists
return (this->use_count() == 0);
}
其中expired则是调用了基类的use_count:
_NODISCARD long use_count() const noexcept
{ // return use count
return (_Rep ? _Rep->_Use_count() : 0);
}
来所引用的资源是否被释放。
而lock则是通过基类_Construct_from_weak函数创建一个临时shared_ptr,并通过移动语义返回。
_NODISCARD shared_ptr<_Ty> lock() const noexcept
{ // convert to shared_ptr
shared_ptr<_Ty> _Ret;
(void) _Ret._Construct_from_weak(*this);
return (_Ret);
}
基类的_Construct_from_weak主要是调用了计数器的_Incref_nz函数实现_Uses的增长,然后在进行拷贝操作。
template<class _Ty2>
bool _Construct_from_weak(const weak_ptr<_Ty2>& _Other)
{ // implement shared_ptr's ctor from weak_ptr, and weak_ptr::lock()
if (_Other._Rep && _Other._Rep->_Incref_nz())
{
_Ptr = _Other._Ptr;
_Rep = _Other._Rep;
return (true);
}
return (false);
}
这里之所以使用_Incref_nz()是为了确保跨线程时_Uses自增成功。