/*shared_ptr.h 文件*/
#ifndef _SHARED_PTR_H
#define _SHARED_PTR_H
template<typename> class shared_ptr ;
template< class T >
void swap( shared_ptr<T>& lhs, shared_ptr<T>& rhs ) noexcept
{
std::cout << "swap out object " << std::endl ;
lhs.swap(rhs);
}
template<typename T>
class shared_ptr {
using DelFuncPtr = void (*)(T*) ;
public:
shared_ptr():m_ptr(nullptr),
count_ptr( new size_t(0)),del(nullptr)
{
}
explicit shared_ptr(T *ptr ,DelFuncPtr temp = nullptr ):
m_ptr(ptr),count_ptr(new size_t(1)), del(temp )
{
}
shared_ptr(const shared_ptr &hp):
m_ptr(hp.m_ptr),count_ptr(hp.count_ptr),del(hp.del)
{
++(*count_ptr) ;
}
shared_ptr& operator=( shared_ptr &rhs){
swap(*this,rhs);
return *this;
}
~shared_ptr(){
--(*count_ptr);
if((*count_ptr) == 0 ){
del ? del(m_ptr):
delete m_ptr;
delete count_ptr ;
}
m_ptr = nullptr ;
count_ptr =nullptr ;
}
size_t use_count(){ return (*count_ptr);}
T& operator*() { return *m_ptr ;}
T* operator->() { return m_ptr ; }
void swap(shared_ptr &hp){
std::cout << "swap in object " << std::endl ;
using std::swap ;
swap(m_ptr,hp.m_ptr);
swap(count_ptr,hp.count_ptr);
swap(del,hp.del);
}
void reset( ){
if((*count_ptr) == 1) {
delete m_ptr;
delete count_ptr ;
m_ptr = nullptr ;
count_ptr =nullptr ;
}
}
void reset( T *hp ,DelFuncPtr del = nullptr ){
shared_ptr temp(hp,del);
swap(temp);
}
private:
T* m_ptr = nullptr ;
size_t* count_ptr = nullptr ;
DelFuncPtr del = nullptr ;
};
#endif
#include <iostream>
#include"shared_ptr.h"
using namespace std ;
struct Foo {
Foo() { std::cout << "Foo()\n"; }
~Foo() { std::cout << "~Foo()\n"; }
Foo(const Foo&) { std::cout << "Foo copy ctor\n"; }
Foo(Foo&&) { std::cout << "Foo move ctor\n"; }
};
struct Fooo {
Fooo(int n = 0) noexcept : bar(n) { std::cout << "Fooo: constructor, bar = " << bar << '\n'; }
~Fooo() { std::cout << "Fooo: destructor, bar = " << bar << '\n'; }
int GetBar() const noexcept { return bar; }
private:
int bar;
};
struct D {
void bar() { std::cout << "Call deleter D::bar()...\n"; }
void operator()(Foo* p) const
{
std::cout << "Call delete from function object...\n";
delete p;
}
};
int main()
{
std::cout << "shared_ptr constructor with no managed object\n";
{
shared_ptr<Foo> sh1;
}
std::cout << "shared_ptr constructor with object and test swap \n";
{
shared_ptr<Foo> sh2(new Foo);
std::cout << sh2.use_count() << '\n';
shared_ptr<Foo> sh3(sh2);
std::cout << sh3.use_count() << '\n';
shared_ptr<int> sh4(new int(4444)) ;
shared_ptr<int> sh5(new int(5555)) ;
sh4.swap(sh5);
cout << "sh4 == " << *sh4 << "\nsh5 == " << *sh5 << endl ;
swap(sh4,sh5);
cout << "sh4 == " << *sh4 << "\nsh5 == " << *sh5 << endl ;
}
std::cout << "shared_ptr constructor with deleter\n";
{
shared_ptr<Foo> sh5(new Foo, [](Foo* p) {
std::cout << "Call delete from lambda...\n";
delete p;
});
}
{
shared_ptr<Fooo> sptr(new Fooo(111)) ;
std::cout << "The first Fooo's bar is " << sptr->GetBar() << "\n";
sptr.reset(new Fooo);
std::cout << "The second Fooo's bar is " << sptr->GetBar() << "\n";
}
}
运行结果:

总结:
- 什么是size_t 类型
它是一个与机器相关的unsigned类型,其大小足以保证存储内存中对象的大小。一般用作下标类型 。
- 为什么是size_t*,而不是 size_t ? ?
因为你要定义的是行为像指针的类而不是像值的类,在多个指针共同指向同一个对象时,只需要拷贝指针,利用指针让它引用计数加一就可以了。如果一个指针被析构时,也是通过指针让引用计数减一即可。
如果为size_t类型的成员变量,在多个shared_ptr对象指向同一资源时,其中一个shared_ptr对象析构了count_ptr = count_ptr -1,但是不会影响到其他shared_ptr对象。所以使用size_t* 来达到多个shared_ptr对象指向同一资源的能够共享count_ptr 的目的。
3 . 另外注意删除器的书写方式和成员函数swap与友元函数swap的书写即可