C++ Smart Pointer
C++ Smart Pointer
arrays template
no deleter ctor
typename = _Require<is_move_constructible<_Del>>>
unique_ptr(pointer __p,
__enable_if_t<!is_lvalue_reference<_Del>::value,
_Del&&> __d) noexcept
: _M_t(__p, std::move(__d))
{ }
template<typename _Del>
__uniq_ptr_impl(pointer __p, _Del&& __d)
: _M_t(__p, std::forward<_Del>(__d)) { }
dtor
~unique_ptr()
{
auto& __ptr = _M_t._M_ptr();
if (__ptr != nullptr)
get_deleter()(__ptr);
__ptr = pointer();
}
reset
swap
get
no lvalue copy
typename add_lvalue_reference<element_type>::type
operator*() const
{
__glibcxx_assert(get() != pointer());
return *get();
}
int main()
{
unique_ptr<int> pInt(new int(5));
// 转移所有权
unique_ptr<int> pInt2 = std::move(pInt);
//cout << *pInt << endl; // 出错,pInt 为空
cout << *pInt2 << endl;
unique_ptr<int> pInt3(std::move(pInt2));
}
share_ptr
ctor
template<typename _Ptr>
explicit __shared_count(_Ptr __p) : _M_pi(0)
{
__try
{
_M_pi = new _Sp_counted_ptr<_Ptr, _Lp>(__p);
}
__catch(...)
{
delete __p;
__throw_exception_again;
}
}
_Sp_counted_base() noexcept
: _M_use_count(1), _M_weak_count(1) { }
move ctor
dtor
~__shared_ptr() = default;
~__shared_count() noexcept
{
if (_M_pi != nullptr)
_M_pi->_M_release();
}
__exchange_and_add_dispatch
use_count unique
类似 size empty
上下行转换
循环引用
#include <iostream>
#include <memory>
#include <vector>
using namespace std;
class ClassB;
class ClassA
{
public:
ClassA() { cout << "ClassA Constructor..." << endl; }
~ClassA() { cout << "ClassA Destructor..." << endl; }
shared_ptr<ClassB> pb; // 在 A 中引用 B
//weak_ptr<ClassB> pb;
};
class ClassB
{
public:
ClassB() { cout << "ClassB Constructor..." << endl; }
~ClassB() { cout << "ClassB Destructor..." << endl; }
shared_ptr<ClassA> pa; // 在 B 中引用 A
//weak_ptr<ClassB> pb;
};
int main()
{
shared_ptr<ClassA> spa = make_shared<ClassA>();
shared_ptr<ClassB> spb = make_shared<ClassB>();
spa->pb = spb;
spb->pa = spa;
std::cout << "spa use_cout:" << spa.use_count() << " spb use_cout:"
<< spb.use_count() << std::endl; //spa: 2 spb:2
}
weak_ptr
ctor
//default ctor
constexpr weak_ptr() noexcept = default;
//copy ctor
weak_ptr(const weak_ptr&) 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;
}
//move ctor
template<typename _Yp, typename = _Constructible<weak_ptr<_Yp>>>
weak_ptr(weak_ptr<_Yp>&& __r) noexcept
: __weak_ptr<_Tp>(std::move(__r)) { }
//shared_ptr ctor
template<typename _Yp,
typename = _Constructible<const shared_ptr<_Yp>&>>
weak_ptr(const shared_ptr<_Yp>& __r) noexcept
: __weak_ptr<_Tp>(__r) { }
dtor
~__weak_ptr() = default;
~__weak_count() noexcept
{
if (_M_pi != nullptr)
_M_pi->_M_weak_release();
}
expired
Equivalent to use_count() == 0. The destructor for the managed object may not yet have been
called, but this object's destruction is imminent (or may have already happened).
Return value
true if the managed object has already been deleted, false otherwise.
lock 获取指针使用权
Creates a new std::shared_ptr that shares ownership of the managed object. If there is no
managed object, i.e. *this is empty, then the returned shared_ptr also is empty.
Effectively returns expired() ? shared_ptr<T>() : shared_ptr<T>(*this), executed
atomically.
void observe(std::weak_ptr<int> weak)
{
if (auto observe = weak.lock()) {
std::cout << "\tobserve() able to lock weak_ptr<>, value=" <<
*observe << "\n";
} else {
std::cout << "\tobserve() unable to lock weak_ptr<>\n";
}
}
int main()
{
std::weak_ptr<int> weak;
std::cout << "weak_ptr<> not yet initialized\n";
observe(weak);
{
auto shared = std::make_shared<int>(42);
weak = shared;
std::cout << "weak_ptr<> initialized with shared_ptr.\n";
observe(weak);
}
class Test
{
public:
std::shared_ptr<Test> GetMe()
{
return std::shared_ptr<Test>(this);
}
};
int main()
{
auto p1 = std::make_shared<Test>();
auto p2 = p1->GetMe();
return 0;
}
shared_ptr<_Tp> shared_from_this()
{
return shared_ptr<_Tp>(this->_M_weak_this);
}
template<typename _Tp1>
void _M_weak_assign(_Tp1* __p, const __shared_count<>& __n) const
noexcept
{
_M_weak_this._M_assign(__p, __n);
}
戳我跳转
效率
code1
new_delete_release
500
450
400
350
300
250
200
150
100
50
0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
10 50 90 130 170 210 250 290 330 370 410 450 490 530 570 610 650 690 730 770 810 850 890 930 970
auto p1 = std::make_shared<uint64_t>();
for(int i = 0; i < count; ++i)
{
auto q = p1;
*q = 0;
}
auto p2 = std::make_shared<uint64_t>();
for(int i = 0; i < count; ++i)
{
auto& q = p2;
*q = 0;
}
assign_debug
300
250
200
150
100
50
0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
10 50 90 130 170 210 250 290 330 370 410 450 490 530 570 610 650 690 730 770 810 850 890 930 970
assign_release
25
20
15
10
0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
10 50 90 130 170 210 250 290 330 370 410 450 490 530 570 610 650 690 730 770 810 850 890 930 970
https://www.youtube.com/watch?v=JfmTagWcqoE&t=763s
unique_ptr
shared_ptr
weak_ptr
graph
deferred_ptr
https://github.com/hsutter/gcpp
总结