智能指针是一个类,它产生的是一个类对象,而不是一个原生的指针对象,但是为了减少类对象与针对对象使用的差异性,所以share_ptr类故意重载了两种常见的指针操作符: *和->。从而share_ptr与普通指针使用方式一样。简言之,就是share_ptr生成的一个包含类型指针容器对象,它封装了指针对象,对指针对象负全责,包括生成、释放等。
智能指针(smart pointer)的一种通用实现技术是使用引用计数(reference count)。智能指针类将一个计数器与类指向的对象相关联,引用计数跟踪该类有多少个对象的指针指向同一对象
- 下面代码为share_pointer的实现,包括:
- 默认构造函数
- 显式定义的自定义构造函数
- 拷贝构造函数
- 移动构造函数
- 拷贝赋值函数
- 移动赋值函数
- *运算符
- ->运算符
- 三个版本的reset函数
- 计数变量设为指针,主要是因为计数是共有的,这样一方面可以节省内存,另一方面可以达到管理共有变量的目的
- destroy函数delete指针时不调用删除器
- 删除器为一个可调用模板,在调用函数中可以用function定义其模式
#ifndef SHAREPOINTER_H
#define SHAREPOINTER_H
#include "DebugDelete.h"
#include <functional>
#include <iostream>
//1.模板成员函数知道使用时编译器才去编译
template<typename T>class share_pointer
{
public:
//默认构造函数
share_pointer(){}
//显式定义构造函数,传递指针管理类型和删除器对象两个形参
explicit share_pointer(T *t, std::function<void(T*)> d = DebugDelete()):t(t),count(new size_t(1)),Deleter(d){}
//拷贝构造函数
share_pointer(share_pointer &sp):count(sp.count),t(sp.t),Deleter(sp.Deleter){
std::cout << "copy" << std::endl;
++*count;
}
//移动构造函数,share_pointer<int> m(share_pointer<int>(new int(30)))调用移动构造函数,若无,则调用拷贝构造函数
share_pointer(share_pointer &&sp):count(sp.count),t(std::move(sp.t)),Deleter(std::move(sp.Deleter)){
std::cout << "moving" << std::endl;
sp.t = nullptr;
}
//赋值构造函数
share_pointer &operator=(share_pointer &sp);
//返回指针指向的值
T& operator*() const {return *t;}
//重载->
T* operator->() const {return &this->operator*();}
//reset
void reset(){
deconstructor();
}
void reset(T* p){
if (t)
{
deconstructor();
t = p;
count = new size_t(1);
}
}
void reset(T* p,std::function<void(T*)> d){
reset(p);
Deleter = d;
}
private:
std::size_t *count;//6.计数为不同对象的公共变量,固定义一个指针,指向共有内存
T *t ;
std::function<void (T*)> Deleter;
void deconstructor();
};
template<typename T>
inline void share_pointer<T>::deconstructor(){
if(t)
{
--*count;
if (*count == 0)
{
Deleter(t);
delete count;
}
}
t = nullptr;
count = nullptr;
}
template<typename T>
inline share_pointer<T> &share_pointer<T>::operator=(share_pointer &sp){
++(*sp.count);
deconstructor();
count = sp.count;
t = sp.t;
Deleter = sp.Deleter;
return *this;
}
#endif
#ifndef DEBUGDELETE_H
#define DEBUGDELETE_H
#include <iostream>
class DebugDelete
{
public:
DebugDelete(std::ostream &s = std::cerr):os(s){} //流无法被拷贝
template<typename T> void operator()(T* t)const
{
os << "deleting ptr" << std::endl;
//std::cout << "t:" << t <<" &t:"<< &t <<" *t:" <<*t << std::endl;
delete t;
//std::cout << "t:" << t <<" &t:"<< &t <<" *t:" <<*t << std::endl;
}
private:
std::ostream &os;//流无法被拷贝
};
#endif
#include "DebugDelete.h"
#include <iostream>
#include "share_pointer.h"
#include <functional>
#include <utility>
#include <iostream>
#include <string>
int _tmain(int argc, _TCHAR* argv[])
{
share_pointer<int> p(new int(20));
share_pointer<int> s(new int(30));
share_pointer<int> q(s);
s = p;
share_pointer<int> m(share_pointer<int>(new int(30)));
int mm = *m;
share_pointer<std::string> n(share_pointer<std::string>(new std::string("hello")));
n.reset();
m.reset(new int(32));
p.reset(new int(43),DebugDelete());
return 0;
}