目录
一、智能指针的通用模板
对于智能指针一般需实现构造、*、->、析构等函数,私有成员包括未定义类型的指针,至于拷贝构造和赋值重载按需实现。
cpp
/*
template<class T>
class smartptr
{
public:
smartptr(T*ptr):_ptr(ptr){}
~smartptr(){if(_ptr) delete _ptr;}
T*operator->() { return _ptr; }
T&operator*() { return *_ptr;}
//拷贝构造和赋值构造......
private:
T*_ptr;
};
*/
二、auto_ptr(禁止使用)
对于auto_ptr(关键实现管理权限的转移)仅供学习,禁止使用
注:
(1)权限的转移,所以构造赋值传参不能加const
(2)赋值重载时,
//1.自己=自己,直接返回自己本身
//2.自己=other,other先改变(释放)原指针的管理,在挂接到新的指针上
cpp
template<class T>
//权限的转移,所以构造赋值传参不能加const
class auto_ptr
{
public:
//无参与有参构造
auto_ptr(T*ptr = nullptr) { _ptr = ptr; }
T*operator->(){return _ptr;}
T&operator*(){return *_ptr;}
//拷贝构造
auto_ptr(auto_ptr<T>&sp)
{
_ptr = sp._ptr;
sp._ptr = nullptr;
}
void release()
{
if(_ptr)
delete _ptr;
}
//赋值构造
auto_ptr&operator=(auto_ptr<T>&sp)
{
//1.自己=自己,直接返回自己本身
//2.自己=other,other先改变(释放)原指针的管理,在挂接到新的指针上
if(_ptr != sp._ptr)
{
release();
_ptr = sp._ptr;
sp._ptr = nullptr;
}
return *this;
}
~auto_ptr()
{
release();
}
private:
T *_ptr;
};
三、unique_ptr
主要是禁止拷贝构造和赋值重载
cpp
template<class T>
//禁止拷贝和赋值
class unique_ptr
{
public:
unique_ptr(T* ptr = nullptr) : _ptr(ptr) {}
T*operator->() { return _ptr; }
T&operator*() { return *_ptr;}
~unique_ptr()
{
if(_ptr)
delete _ptr;
}
T* get() const { return _ptr; }
unique_ptr(const unique_ptr<T>&sp) = delete;
unique_ptr&operator=(const unique_ptr<T>&sp) = delete;
private:
T *_ptr;
};
四、shared_ptr
采用引用计数的方式进行智能指针的管理
注:
(1)//计数方式:
/*1.在堆上开辟一块空间进行计数的维护(make_shared的原理)
2.直接使用int私有成员,表示每一个对象一个计数这样就不合理
3.使用静态成员的话,所有类成员均可见,换一个对象再计数也不合理*/(2)赋值重载和auto_ptr那相同注意点
cpp
// //未加定制删除器
// class shared_ptr
// {
// public:
// shared_ptr(T*ptr = nullptr) : _ptr(ptr), _count(new int(1)) {}
// shared_ptr(const shared_ptr<T>&sp)
// {
// _ptr = sp._ptr;
// _count = sp._count;
// (*_count)++;
// }
// void release()
// {
// if(--(*_count) == 0)
// {
// delete _ptr;
// delete _count;
// }
// }
// //1.自己=自己,直接返回自己本身
// //2.自己=other,自己先改变(释放)原指针的管理,在挂接到新的指针上
// shared_ptr&operator=(const shared_ptr<T>&sp)
// {
// if(_ptr != sp._ptr)
// {
// release();
// _ptr = sp._ptr;
// _count = sp._count;
// (*_count)++;
// }
// return *this;
// }
// ~shared_ptr()
// {
// release();
// }
// T*operator->() {return _ptr;}
// T&operator*() {return *_ptr;}
// int use_count() {return *_count;}
// T*get()const {return _ptr;}
// private:
// T *_ptr;
// int *_count;
// };
五、定制删除器(shared_ptr)
(特殊的函数类型传入相应的析构函数),完成正确的析构,避免内存泄漏
c++标准库引入定制删除器的方式:
//unique_ptr添加定制删除器是实例化模板添加,
unique_ptr<Date[ ]> / unique_ptr<Date[ ],delete[ ]>
//shared_ptr是函数构造时添加的表达式或者仿函数shared_ptr<FILE> sp(fopen("text.cc),fclose(lambda表达式,函数指针,仿函数等))
仅简单手撕shared_ptr版本注:
//若我们直接引入模板进行构造添加,eg:
/*template<class D>
shared_ptr(T*ptr,D del){}*/
//构造析构时无法实例化(类型)和传参lambda表达式和仿函数
//所以引入包装器function,可以对所有的lambda表达式和仿函数进行包装,不用考虑类型
//包装器传入后,对象析构时会调用对象对应的析构(删除器)如果没传的话会内存泄漏,因此我们要有默认形式:
//function<void(T*ptr)> _del = [](T*ptr){delete ptr;};
cpp
class shared_ptr
{
public:
shared_ptr(T*ptr = nullptr) : _ptr(ptr), _count(new int(1)) {}
//定制删除器构造
template<class D>
shared_ptr(T*ptr,D del) : _ptr(ptr), _count(new int(1)),_del(del) {}
shared_ptr(const shared_ptr<T>&sp)
{
_ptr = sp._ptr;
_count = sp._count;
(*_count)++;
}
void release()
{
if(--(*_count) == 0)
{
// delete _ptr;
_del(_ptr);
delete _count;
}
}
//1.自己=自己,直接返回自己本身
//2.自己=other,自己先改变(释放)原指针的管理,在挂接到新的指针上
shared_ptr&operator=(const shared_ptr<T>&sp)
{
if(_ptr != sp._ptr)
{
release();
_ptr = sp._ptr;
_count = sp._count;
(*_count)++;
}
return *this;
}
~shared_ptr()
{
release();
}
T*operator->() {return _ptr;}
T&operator*() {return *_ptr;}
int use_count() {return *_count;}
T*get()const {return _ptr;}
private:
T *_ptr;
int *_count;
function<void(T*ptr)> _del = [](T*ptr){delete ptr;};
};