//SmartPointer,h
#ifndef _SMARTPOINTER_H_
#define _SMARTPOINTER_H_
namespace practice
{
template <typename T>
class pointer
{
protected:
T *m_ptr;
public:
explicit pointer(T *ptr = nullptr) noexcept : m_ptr(ptr)
{
}
pointer(const pointer<T>& obj) noexcept : m_ptr(obj.m_ptr)
{
}
operator bool () const
{
return nullptr != m_ptr;
}
bool operator ! () const
{
return nullptr == m_ptr;
}
T& operator *()
{
return *m_ptr;
}
T *operator -> ()
{
return m_ptr;
}
T& operator *() const
{
return *m_ptr;
}
T *operator -> () const
{
return m_ptr;
}
T *get()
{
return m_ptr;
}
bool is_null() const
{
return nullptr == m_ptr;
}
virtual ~pointer() noexcept
{
}
};
template <typename T>
class unique_ptr : public pointer<T>
{
protected:
void set_null(const unique_ptr<T>& obj)
{
const_cast< unique_ptr<T>& >(obj).m_ptr = nullptr;
}
public:
explicit unique_ptr(T *ptr = nullptr ) noexcept : pointer<T>(ptr)
{
}
unique_ptr(const unique_ptr<T>& obj) noexcept : pointer<T>(obj)
{
set_null(obj);
}
unique_ptr<T>& operator = (const unique_ptr<T>& obj)
{
if( this != &obj )
{
reset(obj.m_ptr);
set_null(obj);
}
return *this;
}
T *take()
{
T *tmp = this->m_ptr;
this->m_ptr = nullptr;
return tmp;
}
void swap(unique_ptr<T>& obj)
{
T *tmp = obj.m_ptr;
obj.m_ptr = this->m_ptr;
this->m_ptr = tmp;
}
void reset(T *ptr = nullptr)
{
delete this->m_ptr;
this->m_ptr = ptr;
}
~unique_ptr() noexcept
{
reset(nullptr);
}
};
template <typename T>
class shared_ptr : public pointer<T>
{
protected:
unsigned *m_count;
void increase_count(const shared_ptr<T>& obj)
{
if( nullptr != obj.m_count )
{
++(*const_cast<shared_ptr<T>& >(obj).m_count);
}
this->m_count = obj.m_count;
}
void decrease_count()
{
if( (nullptr != this->m_count) && (0 == --(*this->m_count)) )
{
delete this->m_ptr;
delete this->m_count;
}
}
public:
explicit shared_ptr( T *ptr = nullptr) noexcept : pointer<T>(ptr)
{
if( nullptr != ptr )
{
this->m_count = new unsigned(1);
}
else
{
this->m_count = nullptr;
}
}
shared_ptr(const shared_ptr<T>& obj) noexcept : pointer<T>(obj)
{
increase_count(obj);
}
shared_ptr<T>& operator = (const shared_ptr<T>& obj)
{
if( this != &obj )
{
decrease_count();
increase_count(obj);
this->m_ptr = obj.m_ptr;
}
return *this;
}
bool unique()
{
return 1 == *this->m_count;
}
unsigned use_count()
{
return *this->m_count;
}
~shared_ptr() noexcept
{
decrease_count();
}
};
}
#endif // _SMARTPOINTER_H_
//main.cpp
#include <iostream>
#include "smartpointer.h"
using namespace std;
class test
{
public:
void print()
{
cout << "test" << endl;
}
};
void test_unique()
{
practice::unique_ptr<int> p(new int(10));
if( p )
{
cout << "if( p )" << endl;
}
practice::unique_ptr<int> p2(p);
if( !p )
{
cout << "if( !p )" << endl;
}
p = p2;
if( p2.is_null() )
{
cout << "p2.is_null()" << endl;
}
p2.swap(p);
if( nullptr != p2.get() )
{
cout << "nullptr != p2.get()" << endl;
}
cout << "*p2 = " << *p2 << endl;
int *t = p2.take();
cout << "*t = " << *t << endl;
delete t;
p2.reset(new int(0));
cout << "*p2 = " << *p2 << endl;
practice::unique_ptr<test> pt(new test);
pt->print();
}
void test_share()
{
practice::shared_ptr<int> p(new int(100));
if( p )
{
cout << "if( p )" << endl;
}
if( false == !p )
{
cout << "false == !p" << endl;
}
practice::shared_ptr<int> p2(p);
if( 2 == p.use_count() )
{
cout << "2 == p.use_count()" << endl;
}
p = p2;
practice::shared_ptr<int> p3(new int(1));
p2 = p3;
if( p.unique() )
{
cout << "p.unique()" << endl;
}
*p = 10;
cout << "*p = " << *p << endl;
cout <<"* p3.get() = " << * p3.get() << endl;
practice::shared_ptr<test> p4(new test);
p4->print();
}
int main()
{
test_unique();
test_share();
return 0;
}
//本来想加上删除器的,无奈,模板暂时没有好的方法使模板实参个数与构造函数实参个数一致,按照对标准库中的智能指针的测试来看,拿std::uniq_ptr来说:
std::uniq_ptr的两个模板参数,第一个为内部管理的指针指向的对象类型,第二个参数为删除器类型,虽然说第二个模板参数可以是默认删除器,但只要为模板类提供了删除器类型,就必须使用两个实参去调用构造函数,使用一个实参调用构造函数编译器报错,同样的,如果使用默认模板删除器,必须使用一个实参去调用构造函数,使用两个实参编译器报错。如 std::uniq_ptr<int, void(*)(int *)> p(&a)与std::uniq_ptr<int> p2(&a, fun)编译器应该报错,因为模板实参个数与构造函数实参个数不一致,std::uniq_ptr<int, void(*)(int *)> p(&a, func)与std::uniq_ptr<int> p2(&a)编译器不会报错,但是我目前不能做到这一点。
删除器是一个可调用对象,其参数为智能指针内部封装的原生指针,使用默认删除器的情况下,智能指着的析构函数被调用时,删除器其会对原生指针进行释放操作,delete (p),如果传入了自定义的删除器,将会是deleter(p)