目录
一、关键点解析
1、__GXX_RTTI
2、typeid
3、?_Sp_make_shared_tag
4、? typedef typename _Alloc::template rebind<_Tp>::other _Alloc2;
5、_Deleter<_Alloc2> __del = { _Alloc2(__a) };
6、common_type
二、源码分析
一、关键点解析
1、__GXX_RTTI
? ? ? ? ? This macro is defined, with value 1, when compiling a C++ source?file with runtime type identification enabled. ?If '-fno-rtti' isused when compiling the file, then this macro is not defined.
? ? ? ? ?默认定义为1,如果不需要在编译器选项里面加上'-fno-rtti'。如果加上'-fno-rtti' typeid就用不了了。
2、typeid
? ? ? ?typeid 运算符用来获取一个表达式的类型信息。类型信息对于编程语言非常重要,它描述了数据的各种属性:
(1)对于基本类型(int、float 等C++内置类型)的数据,类型信息所包含的内容比较简单,主要是指数据的类型。
(2)对于类类型的数据(也就是对象),类型信息是指对象所属的类、所包含的成员、所在的继承关系等。
3、?_Sp_make_shared_tag
? ?__shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a, ?? ??? ? ? ? _Args&&... __args)
// This constructor is non-standard, it is used by allocate_shared.
template<typename _Alloc, typename... _Args>
__shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a,
_Args&&... __args)
: _M_ptr(), _M_refcount(__tag, (_Tp*)0, __a,
std::forward<_Args>(__args)...)
{
// _M_ptr needs to point to the newly constructed object.
// This relies on _Sp_counted_ptr_inplace::_M_get_deleter.
void* __p = _M_refcount._M_get_deleter(typeid(__tag));
_M_ptr = static_cast<_Tp*>(__p);
__enable_shared_from_this_helper(_M_refcount, _M_ptr, _M_ptr);
}
?void* __p = _M_refcount._M_get_deleter(typeid(__tag))最终会调用到_Sp_counted_ptr_inplace::_M_get_deleter
struct _Sp_make_shared_tag { };
template<typename _Tp, typename _Alloc, _Lock_policy _Lp>
class _Sp_counted_ptr_inplace final : public _Sp_counted_base<_Lp>
{
..........
virtual void*
_M_get_deleter(const std::type_info& __ti) noexcept
{
#ifdef __GXX_RTTI
if (__ti == typeid(_Sp_make_shared_tag))
return const_cast<typename remove_cv<_Tp>::type*>(_M_ptr());
#endif
return nullptr;
}
private:
_Tp* _M_ptr() noexcept { return _M_impl._M_storage._M_ptr(); }
..........
}
_Sp_make_shared_tag 作为一个使用预先分配内存的tag。
4、? typedef typename _Alloc::template rebind<_Tp>::other _Alloc2;
头文件allocator.h
template<typename _Tp1>
struct rebind
{ typedef allocator<_Tp1> other; };
5、_Deleter<_Alloc2> __del = { _Alloc2(__a) };
c++11中 可以使用花括号直接初始化结构体,示例代码如下:
#include<iostream>
#include<string>
struct TT{
int t1;
std::string t2;
};
int main(){
TT t{1,"hello"};
std::cout << t.t1 << ", " << t.t2 << std::endl;
return 0;
}
template<typename _Alloc>
struct _Deleter
{
void operator()(_Tp* __ptr)
{
typedef allocator_traits<_Alloc> _Alloc_traits;
_Alloc_traits::destroy(_M_alloc, __ptr);
_Alloc_traits::deallocate(_M_alloc, __ptr, 1);
}
_Alloc _M_alloc;
};
typedef typename _Alloc::template rebind<_Tp>::other _Alloc2;
_Deleter<_Alloc2> __del = { _Alloc2(__a) };
_Deleter<_Alloc2> __del = { _Alloc2(__a) }这句的意思也就是初始化一个结构体。
6、common_type
#include <type_traits>
#include<typeinfo>
int main()
{
// std::common_type<int,float,double>::type // 返回值为double
typedef std::common_type<int, float, double>::type test;
std::cout << "test is a int " << std::is_same<int, test>::value<< std::endl;
std::cout << "test is a float " << std::is_same<float, test>::value<< std::endl;
std::cout << "test is a double " << std::is_same<double, test>::value << std::endl;;
//typedef std::common_type<char,int>::type test2; // 报错,无法互相转换
return 0;
}
二、源码分析
template<typename _Tp, _Lock_policy _Lp>
class __shared_ptr
{
public:
typedef _Tp element_type;// element_type即为_Tp类型
constexpr __shared_ptr() noexcept//constexpr 构造函数
: _M_ptr(0), _M_refcount()
{ }
template<typename _Tp1>
explicit __shared_ptr(_Tp1* __p)
: _M_ptr(__p), _M_refcount(__p)
{
__glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)//指针时可以赋值的
static_assert( !is_void<_Tp1>::value, "incomplete type" );//不是void类型
static_assert( sizeof(_Tp1) > 0, "incomplete type" );//类型大小大于0
__enable_shared_from_this_helper(_M_refcount, __p, __p);//添加一个弱引用
}
template<typename _Tp1, typename _Deleter>
__shared_ptr(_Tp1* __p, _Deleter __d)
: _M_ptr(__p), _M_refcount(__p, __d)//构造函数
{
__glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
// TODO requires _Deleter CopyConstructible and __d(__p) well-formed
__enable_shared_from_this_helper(_M_refcount, __p, __p);
}
template<typename _Tp1, typename _Deleter, typename _Alloc>
__shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a)//构造函数
: _M_ptr(__p), _M_refcount(__p, __d, std::move(__a))
{
__glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
// TODO requires _Deleter CopyConstructible and __d(__p) well-formed
__enable_shared_from_this_helper(_M_refcount, __p, __p);
}
template<typename _Deleter>
__shared_ptr(nullptr_t __p, _Deleter __d)
: _M_ptr(0), _M_refcount(__p, __d)
{ }
template<typename _Deleter, typename _Alloc>
__shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
: _M_ptr(0), _M_refcount(__p, __d, std::move(__a))
{ }
template<typename _Tp1>
__shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r, _Tp* __p) noexcept
: _M_ptr(__p), _M_refcount(__r._M_refcount) // never throws
{ }
__shared_ptr(const __shared_ptr&) noexcept = default;
__shared_ptr& operator=(const __shared_ptr&) noexcept = default;
~__shared_ptr() = default;
template<typename _Tp1, typename = typename
std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
__shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
: _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount)
{ }
__shared_ptr(__shared_ptr&& __r) noexcept//右值构造函数实现move语义
: _M_ptr(__r._M_ptr), _M_refcount()
{
_M_refcount._M_swap(__r._M_refcount);//调用__shared_count类中的_M_swap
__r._M_ptr = 0;
}
template<typename _Tp1, typename = typename
std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
__shared_ptr(__shared_ptr<_Tp1, _Lp>&& __r) noexcept
: _M_ptr(__r._M_ptr), _M_refcount()
{
_M_refcount._M_swap(__r._M_refcount);
__r._M_ptr = 0;
}
template<typename _Tp1>
explicit __shared_ptr(const __weak_ptr<_Tp1, _Lp>& __r)
: _M_refcount(__r._M_refcount) // may throw
{
__glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
// It is now safe to copy __r._M_ptr, as
// _M_refcount(__r._M_refcount) did not throw.
_M_ptr = __r._M_ptr;
}
// If an exception is thrown this constructor has no effect.
template<typename _Tp1, typename _Del>
__shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r)
: _M_ptr(__r.get()), _M_refcount()
{
__glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
auto __raw = _S_raw_ptr(__r.get());
_M_refcount = __shared_count<_Lp>(std::move(__r));
__enable_shared_from_this_helper(_M_refcount, __raw, __raw);
}
#if _GLIBCXX_USE_DEPRECATED
// Postcondition: use_count() == 1 and __r.get() == 0
template<typename _Tp1>
__shared_ptr(std::auto_ptr<_Tp1>&& __r);
#endif
/* TODO: use delegating constructor */
constexpr __shared_ptr(nullptr_t) noexcept
: _M_ptr(0), _M_refcount()
{ }
template<typename _Tp1>
__shared_ptr&
operator=(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
{
_M_ptr = __r._M_ptr;
_M_refcount = __r._M_refcount; // __shared_count::op= doesn't throw
return *this;
}
#if _GLIBCXX_USE_DEPRECATED
template<typename _Tp1>
__shared_ptr&
operator=(std::auto_ptr<_Tp1>&& __r)
{
__shared_ptr(std::move(__r)).swap(*this);
return *this;
}
#endif
__shared_ptr&
operator=(__shared_ptr&& __r) noexcept
{
__shared_ptr(std::move(__r)).swap(*this);
return *this;
}
template<class _Tp1>
__shared_ptr&
operator=(__shared_ptr<_Tp1, _Lp>&& __r) noexcept
{
__shared_ptr(std::move(__r)).swap(*this);
return *this;
}
template<typename _Tp1, typename _Del>
__shared_ptr&
operator=(std::unique_ptr<_Tp1, _Del>&& __r)
{
__shared_ptr(std::move(__r)).swap(*this);
return *this;
}
void
reset() noexcept
{ __shared_ptr().swap(*this); }
template<typename _Tp1>
void
reset(_Tp1* __p) // _Tp1 must be complete.
{
// Catch self-reset errors.
_GLIBCXX_DEBUG_ASSERT(__p == 0 || __p != _M_ptr);
__shared_ptr(__p).swap(*this);
}
template<typename _Tp1, typename _Deleter>
void
reset(_Tp1* __p, _Deleter __d)
{ __shared_ptr(__p, __d).swap(*this); }
template<typename _Tp1, typename _Deleter, typename _Alloc>
void
reset(_Tp1* __p, _Deleter __d, _Alloc __a)
{ __shared_ptr(__p, __d, std::move(__a)).swap(*this); }
// Allow class instantiation when _Tp is [cv-qual] void.
typename std::add_lvalue_reference<_Tp>::type
operator*() const noexcept
{
_GLIBCXX_DEBUG_ASSERT(_M_ptr != 0);
return *_M_ptr;
}
_Tp*
operator->() const noexcept
{
_GLIBCXX_DEBUG_ASSERT(_M_ptr != 0);
return _M_ptr;
}
_Tp*
get() const noexcept
{ return _M_ptr; }
explicit operator bool() const // never throws
{ return _M_ptr == 0 ? false : true; }
bool
unique() const noexcept
{ return _M_refcount._M_unique(); }
long
use_count() const noexcept
{ return _M_refcount._M_get_use_count(); }
void
swap(__shared_ptr<_Tp, _Lp>& __other) noexcept
{
std::swap(_M_ptr, __other._M_ptr);
_M_refcount._M_swap(__other._M_refcount);
}
template<typename _Tp1>
bool
owner_before(__shared_ptr<_Tp1, _Lp> const& __rhs) const
{ return _M_refcount._M_less(__rhs._M_refcount); }
template<typename _Tp1>
bool
owner_before(__weak_ptr<_Tp1, _Lp> const& __rhs) const
{ return _M_refcount._M_less(__rhs._M_refcount); }
#ifdef __GXX_RTTI
protected:
// This constructor is non-standard, it is used by allocate_shared.
template<typename _Alloc, typename... _Args>
__shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a,
_Args&&... __args)
: _M_ptr(), _M_refcount(__tag, (_Tp*)0, __a,
std::forward<_Args>(__args)...)
{
// _M_ptr needs to point to the newly constructed object.
// This relies on _Sp_counted_ptr_inplace::_M_get_deleter.
void* __p = _M_refcount._M_get_deleter(typeid(__tag));
_M_ptr = static_cast<_Tp*>(__p);
__enable_shared_from_this_helper(_M_refcount, _M_ptr, _M_ptr);
}
#else
template<typename _Alloc>
struct _Deleter
{
void operator()(_Tp* __ptr)
{
typedef allocator_traits<_Alloc> _Alloc_traits;
_Alloc_traits::destroy(_M_alloc, __ptr);
_Alloc_traits::deallocate(_M_alloc, __ptr, 1);
}
_Alloc _M_alloc;
};
template<typename _Alloc, typename... _Args>
__shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a,
_Args&&... __args)
: _M_ptr(), _M_refcount()
{
typedef typename _Alloc::template rebind<_Tp>::other _Alloc2;
_Deleter<_Alloc2> __del = { _Alloc2(__a) };
typedef allocator_traits<_Alloc2> __traits;
_M_ptr = __traits::allocate(__del._M_alloc, 1);
__try
{
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 2070. allocate_shared should use allocator_traits<A>::construct
__traits::construct(__del._M_alloc, _M_ptr,
std::forward<_Args>(__args)...);
}
__catch(...)
{
__traits::deallocate(__del._M_alloc, _M_ptr, 1);
__throw_exception_again;
}
__shared_count<_Lp> __count(_M_ptr, __del, __del._M_alloc);
_M_refcount._M_swap(__count);
__enable_shared_from_this_helper(_M_refcount, _M_ptr, _M_ptr);
}
#endif
template<typename _Tp1, _Lock_policy _Lp1, typename _Alloc,
typename... _Args>
friend __shared_ptr<_Tp1, _Lp1>
__allocate_shared(const _Alloc& __a, _Args&&... __args);
// This constructor is used by __weak_ptr::lock() and
// shared_ptr::shared_ptr(const weak_ptr&, std::nothrow_t).
__shared_ptr(const __weak_ptr<_Tp, _Lp>& __r, std::nothrow_t)
: _M_refcount(__r._M_refcount, std::nothrow)
{
_M_ptr = _M_refcount._M_get_use_count() ? __r._M_ptr : nullptr;
}
friend class __weak_ptr<_Tp, _Lp>;
private:
void*
_M_get_deleter(const std::type_info& __ti) const noexcept
{ return _M_refcount._M_get_deleter(__ti); }
template<typename _Tp1>
static _Tp1*
_S_raw_ptr(_Tp1* __ptr)
{ return __ptr; }
template<typename _Tp1>
static auto
_S_raw_ptr(_Tp1 __ptr) -> decltype(std::__addressof(*__ptr))
{ return std::__addressof(*__ptr); }
template<typename _Tp1, _Lock_policy _Lp1> friend class __shared_ptr;
template<typename _Tp1, _Lock_policy _Lp1> friend class __weak_ptr;
template<typename _Del, typename _Tp1, _Lock_policy _Lp1>
friend _Del* get_deleter(const __shared_ptr<_Tp1, _Lp1>&) noexcept;
_Tp* _M_ptr; // Contained pointer.
__shared_count<_Lp> _M_refcount; // Reference counter.
};
// 20.7.2.2.7 shared_ptr comparisons
template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
inline bool
operator==(const __shared_ptr<_Tp1, _Lp>& __a,
const __shared_ptr<_Tp2, _Lp>& __b) noexcept
{ return __a.get() == __b.get(); }
template<typename _Tp, _Lock_policy _Lp>
inline bool
operator==(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
{ return !__a; }
template<typename _Tp, _Lock_policy _Lp>
inline bool
operator==(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
{ return !__a; }
template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
inline bool
operator!=(const __shared_ptr<_Tp1, _Lp>& __a,
const __shared_ptr<_Tp2, _Lp>& __b) noexcept
{ return __a.get() != __b.get(); }
template<typename _Tp, _Lock_policy _Lp>
inline bool
operator!=(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
{ return (bool)__a; }
template<typename _Tp, _Lock_policy _Lp>
inline bool
operator!=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
{ return (bool)__a; }
template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
inline bool
operator<(const __shared_ptr<_Tp1, _Lp>& __a,
const __shared_ptr<_Tp2, _Lp>& __b) noexcept
{
typedef typename std::common_type<_Tp1*, _Tp2*>::type _CT;
return std::less<_CT>()(__a.get(), __b.get());
}
template<typename _Tp, _Lock_policy _Lp>
inline bool
operator<(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
{ return std::less<_Tp*>()(__a.get(), nullptr); }
template<typename _Tp, _Lock_policy _Lp>
inline bool
operator<(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
{ return std::less<_Tp*>()(nullptr, __a.get()); }
template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
inline bool
operator<=(const __shared_ptr<_Tp1, _Lp>& __a,
const __shared_ptr<_Tp2, _Lp>& __b) noexcept
{ return !(__b < __a); }
template<typename _Tp, _Lock_policy _Lp>
inline bool
operator<=(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
{ return !(nullptr < __a); }
template<typename _Tp, _Lock_policy _Lp>
inline bool
operator<=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
{ return !(__a < nullptr); }
template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
inline bool
operator>(const __shared_ptr<_Tp1, _Lp>& __a,
const __shared_ptr<_Tp2, _Lp>& __b) noexcept
{ return (__b < __a); }
template<typename _Tp, _Lock_policy _Lp>
inline bool
operator>(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
{ return std::less<_Tp*>()(nullptr, __a.get()); }
template<typename _Tp, _Lock_policy _Lp>
inline bool
operator>(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
{ return std::less<_Tp*>()(__a.get(), nullptr); }
template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
inline bool
operator>=(const __shared_ptr<_Tp1, _Lp>& __a,
const __shared_ptr<_Tp2, _Lp>& __b) noexcept
{ return !(__a < __b); }
template<typename _Tp, _Lock_policy _Lp>
inline bool
operator>=(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
{ return !(__a < nullptr); }
template<typename _Tp, _Lock_policy _Lp>
inline bool
operator>=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
{ return !(nullptr < __a); }
template<typename _Sp>
struct _Sp_less : public binary_function<_Sp, _Sp, bool>
{
bool
operator()(const _Sp& __lhs, const _Sp& __rhs) const noexcept
{
typedef typename _Sp::element_type element_type;
return std::less<element_type*>()(__lhs.get(), __rhs.get());
}
};
template<typename _Tp, _Lock_policy _Lp>
struct less<__shared_ptr<_Tp, _Lp>>
: public _Sp_less<__shared_ptr<_Tp, _Lp>>
{ };
// 20.7.2.2.8 shared_ptr specialized algorithms.
template<typename _Tp, _Lock_policy _Lp>
inline void
swap(__shared_ptr<_Tp, _Lp>& __a, __shared_ptr<_Tp, _Lp>& __b) noexcept
{ __a.swap(__b); }
// 20.7.2.2.9 shared_ptr casts
// The seemingly equivalent code:
// shared_ptr<_Tp, _Lp>(static_cast<_Tp*>(__r.get()))
// will eventually result in undefined behaviour, attempting to
// delete the same object twice.
/// static_pointer_cast
template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
inline __shared_ptr<_Tp, _Lp>
static_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
{ return __shared_ptr<_Tp, _Lp>(__r, static_cast<_Tp*>(__r.get())); }
// The seemingly equivalent code:
// shared_ptr<_Tp, _Lp>(const_cast<_Tp*>(__r.get()))
// will eventually result in undefined behaviour, attempting to
// delete the same object twice.
/// const_pointer_cast
template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
inline __shared_ptr<_Tp, _Lp>
const_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
{ return __shared_ptr<_Tp, _Lp>(__r, const_cast<_Tp*>(__r.get())); }
// The seemingly equivalent code:
// shared_ptr<_Tp, _Lp>(dynamic_cast<_Tp*>(__r.get()))
// will eventually result in undefined behaviour, attempting to
// delete the same object twice.
/// dynamic_pointer_cast
template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
inline __shared_ptr<_Tp, _Lp>
dynamic_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
{
if (_Tp* __p = dynamic_cast<_Tp*>(__r.get()))
return __shared_ptr<_Tp, _Lp>(__r, __p);
return __shared_ptr<_Tp, _Lp>();
}
|