关于shared_ptr模板和unique_ptr模板的实现
来源:互联网 发布:洛克人网络争霸战01 编辑:程序博客网 时间:2024/06/08 10:03
在c++primer16.1这一节有这样的题目:
让我们实现自己的shared_pr和unique_ptr模板
如果没有删除器的传入,那么这两个模板的实现并不算难,shared_ptr共享指针,只需要为它多申请一块内存用来存放引用次数就可以了。
但是在这一节介绍了shared_ptr和unique_ptr传入删除器的不同点,如果要加入删除器的传入,那就是个很大的挑战了。
首先的问题,我们应该如何储存传入的删除器?
对于shared_ptr,我做了几个测试,传入的删除器要有以下的特点:
1.传入的删除器参数只能有一个(析构函数会对指向的调用我们传入的删除器)
2.模板实参类型的指针必须可以转换成为传入的删除器的参数(比如指向string,那么传入的删除器的参数应该是string*)
除此之外便没有什么别的限定了,甚至于,删除器的返回类型可以是int而不是void。
而且当我们运行时候才知道删除器的具体类型,我们可以向他传入函数对象,也可以传入函数指针,我们可以通过reset来改变他的删除器类型
这意味着删除器可能并不是一个成员,而是一个类似于指针的东西。因为直接作为成员是无法转换类型的。不过可以存放函数对象,又可以存放函数指针的东西又有什么?
刚开始我用了void指针,但是有下面两个问题:
1.的确它可以指向任何指针,但是它似乎不能指向函数对象。我们传入函数对象时,可能必须使用取址符&,这不是想要的结果。
2.为了使用void指针指向的函数,我们必须对他进行类型转换,否则无法调用。而进行了强制转换后,又有一个问题,即使我们传入的指针完全不符合上述两点要求,
它也会转换而不会报错。当然这样的行为是未定义的。
这时候前两天看到的叫做function的标准库类型便显得比较有用了。它可以储存函数指针,函数对象,lambda表达式,只要他们的调用方式相同。虽然依然有问题,比如返回值的问题,我们在一开始就给他了参数void(T*),那么返回值非int的就不能传入,但是相对于之前,这也是很大的进步了。
下面写一下用function的源码
#pragma once
#include<functional>
using std::function;
template <typename T> class make_shared;
template <typename T>
class shared_ptr
{
typedef function<void(T*)> deletype;
friend class make_shared<T>;
public:
shared_ptr() = default;
shared_ptr(T* t,deletype de = [](T*a) {delete a; }) :data(t), refer_time(new size_t()),dele(de) { ++*refer_time; }
shared_ptr(const shared_ptr<T> &t):data(t.data), refer_time(t.refer_time), dele(t.dele) { ++*refer_time; }
shared_ptr(const shared_ptr<T> &t, deletype de) :data(t.data), refer_time(t.refer_time), dele(de) { ++*refer_time; }
~shared_ptr() { free(); }
void reset() { data = nullptr; --*refer_time; refer_time = nullptr; dele = [](T*a) {delete a; }; }
void reset(T*t, deletype de = [](T*a) { delete a; })
{
free();
data = t;
refer_time = new size_t();
++*refer_time;
dele = de;
}
T& operator*()
{
return *data;
}
shared_ptr &operator = (const shared_ptr<T> & sp)
{
++*(sp.refer_time);//为了支持自赋值,我们必须先这样,否则内存可能提前释放
free();
data = sp.data;
refer_time = sp.refer_time();
dele = sp.dele;
}
private:
T* data=nullptr;//指针指向的
size_t * refer_time = nullptr;//引用次数
deletype dele;//保存删除器
void free();
};
template <typename T> void shared_ptr<T>::free()
{
if (!(--*refer_time))
{
delete refer_time;
dele(data);
}
}
在上述代码中,如果没有传入删除器,我们将调用一个lambda表达式,毕竟我们不能像判断指针是否为空一样判断function对象
当然我们可以通过判断function是否是空,然后来决定是否应该调用delete来删除,不过在本质上这和用lambda表达式是没有区别的
值得注意的是 我们在类内每次都要把lambda表达式打出来,而不能用auto f = [](T*a){delete a;}然后每次写 等于 f就行,因为在类内它会被当作一个成员。
上述基本是这样,但是我们依然无法传入int型的,这个我也不清楚,似乎要用到类型擦除。或者可能用到any类,这个以后再说
对于unique_ptr模板来说,虽然他是指针,但是他独享他指向的对象,这意味着它不能拷贝,但是是支持移动赋值等操作的。所以他也没有引用次数等等一说
这样他的这些部分的实现可能比shared_ptr更简单。
对于删除器,我们要像unique_ptr类型传入删除器,就要在声明时候显示传入删除器的类型。
如果我们要显示传入删除器,这固然是很容易实现的,不过他的实现难在默认的部分。
因为上述原因,所以我们知道unique_ptr的模板有两个参数。其中第二个参数是有默认参数
那他的默认参数应该是什么?是指向函数的指针吗?
因为删除器是类的一部分,所以即使默认的他也应该存在,我们可以直接调用dele,而不用做什么判断。
- 关于shared_ptr模板和unique_ptr模板的实现
- std::unique_ptr和std::shared_ptr的用法
- C++实现智能指针(shared_ptr和unique_ptr)与删除器
- 模板共享指针(shared_ptr)原理实现
- C++ 智能指针shared_ptr模板实现原理
- 关于std:auto_ptr std:shared_ptr std:unique_ptr
- 关于模板类的实现
- C++智能指针 shared_ptr,unique_ptr和weak_ptr
- GCC4.7.0库里的shared_ptr,weak_ptr和unique_ptr的简单讲解(抛砖求玉,有图有真相)
- 模板的声明和实现
- 关于模板类和模板函数的经典文章
- 关于函数模板和类模板的应用
- unique_ptr的一个实现
- shared_ptr / unique_ptr不完全类型
- shared_ptr/unique_ptr一点体会
- unique_ptr and shared_ptr
- shared_ptr,weak_ptr,unique_ptr
- C++11中使用shared_ptr和unique_ptr管理动态数组
- POJ 1236 Network of Schools【强连通缩点】
- Java序列化的几种方式以及序列化的作用
- TokuDB7.5.7-2.4.2TokuDB的几个文件目录
- imageload的简单实用
- 图结构练习——BFS——从起始点到目标点的最短步数
- 关于shared_ptr模板和unique_ptr模板的实现
- 面向过程与面向对象
- 用canvas绘制一个圆形,实现绕着一个中心运动
- effective C++之绝不要重定义基类的non virtual函数
- 经典问题五.(乘号两边有正负 区间dp)Polygon poj 1179
- 19个必须知道的Visual Studio快捷键
- swoole中文乱码
- OpenGL列向量和OSG行向量
- Retrofit网络框架入门使用