C++——智能指针unique_ptr的实现
- 起初,我最直观的设计想法,直接设计一个类:包含全部要素(对象,指针计数)。然后提供出去。
class CPoint
{
public:
CPoint(int xVal = , int yVal = ) : x(xVal), y(yVal) {}
int getX() const { return x; }
int getY() const { return y; }
void setX(int xVal) { x = xVal; }
void setY(int yVal) { y = yVal; } private:
int x, y;
}; class CSmartPtr
{
public:
CSmartPtr(CPoint *ptr) : m_pPoint(ptr),m_count() {}
CSmartPtr(const CSmartPtr &sptr) : m_pPoint(sptr.m_pPoint),m_count(sptr.m_count) {} ~CSmartPtr()
{
Release();
}
CPoint* get()
{
return m_pPoint;
}
/*此处不知道如何有效实现,既能提供出去,有把内部清空????*/
CPoint *release()
{
m_count = ;
return m_pPoint;
}
int user_count() { return m_count; }
CPoint &operator*()
{
return *(m_pPoint);
} CPoint *operator->()
{
return m_pPoint;
} private:
void Release()
{
if (m_count-- == )
{
delete m_pPoint;
}
else
{
cout << "引用次数:" << m_count << endl;
}
} int m_count;
CPoint *m_pPoint;
};
但是我实现到release方法的时候,并不能满足需求。因为release方法的要求是,交出对象的控制权,然后智能指针指向null;Releases ownership of its stored pointer, by returning its value and replacing it with a null pointer.这就尴尬了。因此采用了将指针计数和对象单独拿出来的做法,也就是网上其他博客中常见的做法。但我还不是很理解他们那种做法的解释。

代码实现:
class CPoint
{
public:
CPoint(int xVal = , int yVal = ) : x(xVal), y(yVal) {}
int getX() const { return x; }
int getY() const { return y; }
void setX(int xVal) { x = xVal; }
void setY(int yVal) { y = yVal; } private:
int x, y;
};
class CSmartPtr;
/* */
class CCountPtr
{
private:
friend class CSmartPtr;
int m_count;
CPoint *m_pPoint;
CCountPtr(CPoint *ptr):m_pPoint(ptr),m_count(){}
~CCountPtr()
{
m_count=;
}
}; class CSmartPtr
{
public:
CSmartPtr(CPoint *ptr) : m_pCountPtr (new CCountPtr(ptr)){}
CSmartPtr(const CSmartPtr &sptr) : m_pCountPtr(sptr.m_pCountPtr) {}
CSmartPtr& operator=(const CSmartPtr &sptr)
{
(sptr.m_pCountPtr->m_count)++;
minusOne();
m_pCountPtr = sptr.m_pCountPtr;
return *this;
}
~CSmartPtr()
{
minusOne();
}
CPoint *get()
{
return m_pCountPtr->m_pPoint;
}
CPoint *release()
{
CPoint *pRet = m_pCountPtr->m_pPoint;
m_pCountPtr->m_pPoint = nullptr;
m_pCountPtr->m_count = ;
return pRet;
}
/*Destroys the object currently managed by the unique_ptr (if any) and takes ownership of p.*/
void reset(CPoint *pPoint)
{
minusOne();
m_pCountPtr = new CCountPtr(pPoint);
}
void swap(CSmartPtr &x)
{
CPoint *pRet = m_pCountPtr->m_pPoint;
int count = m_pCountPtr->m_count; m_pCountPtr->m_pPoint = x.m_pCountPtr->m_pPoint;
m_pCountPtr->m_count = x.m_pCountPtr->m_count; x.m_pCountPtr->m_pPoint = pRet;
x.m_pCountPtr->m_count = count;
} int user_count(){return m_pCountPtr->m_count; }
CPoint& operator *()
{
return *(m_pCountPtr->m_pPoint);
} CPoint* operator ->()
{
return m_pCountPtr->m_pPoint;
} private:
void minusOne()
{
if (m_pCountPtr->m_count-- == )
{
delete m_pCountPtr;
m_pCountPtr = nullptr;
}
else
{
cout << "引用次数:" << m_pCountPtr->m_count << endl;
}
}
CCountPtr *m_pCountPtr;
}; int main()
{
CPoint *pPoint = new CPoint(,);
{
CSmartPtr sptr1(pPoint);
{
(*sptr1).setX();
cout<<"initial:"<<endl;
cout << "sptr1->getX(): " << sptr1->getX() << endl;
CPoint *pPoint2 = new CPoint(, );
/*测试swap*/
cout << "swap:" << endl;
CPoint *pPoint4 = new CPoint(, );
CSmartPtr sptr2(pPoint4);
sptr1.swap(sptr2);
cout << "sptr1->getX(): " << sptr1->getX() << endl;
cout << "sptr2->getX(): " << sptr2->getX() << endl;
/*测试reset*/
cout << "reset:" << endl;
sptr1.reset(pPoint2);
cout << "sptr1->getX(): " << sptr1->getX() << endl;
/*测试release*/
cout << "release:" << endl;
CPoint *pPoint3 = new CPoint(, );
pPoint3 = sptr1.release();
cout << "pPoint3->getX(): " << pPoint3->getX() << endl;
cout << "sptr1.count: " << sptr1.user_count() << endl;
}
cout<<"sptr1.count: "<< sptr1.user_count()<<endl;
} cout<<"pPoint.getx(): "<<pPoint->getX()<<endl;
system("pause");
return ;
}
2.模板类。改进一下即可。将CPoint换成泛型表达。
template <typename T>
class CSmartPtr; template <typename T>
class CCountPtr
{
private:
friend class CSmartPtr<T>;
int m_count;
T *m_pT;
CCountPtr(T *ptr) : m_pT(ptr), m_count() {}
~CCountPtr(){}
}; template <typename T>
class CSmartPtr
{
public:
CSmartPtr(T *ptr) : m_pCountPtr (new CCountPtr<T>(ptr)){}
CSmartPtr(const CSmartPtr &sptr) : m_pCountPtr(sptr.m_pCountPtr) {}
CSmartPtr& operator=(const CSmartPtr &sptr)
{
(sptr.m_pCountPtr->m_count)++;
minusOne();
m_pCountPtr = sptr.m_pCountPtr;
return *this;
} ~CSmartPtr()
{
minusOne();
}
T * get()
{
return m_pCountPtr->m_pPoint;
}
T *release()
{
T *pRet = m_pCountPtr->m_pPoint;
m_pCountPtr->m_pPoint = nullptr;
m_pCountPtr->m_count = ;
return pRet;
}
/*Destroys the object currently managed by the unique_ptr (if any) and takes ownership of p.*/
void reset(T *pPoint)
{
minusOne();
m_pCountPtr = new CCountPtr<T>(pPoint);
}
void swap(CSmartPtr &x)
{
T *pRet = m_pCountPtr->m_pPoint;
int count = m_pCountPtr->m_count; m_pCountPtr->m_pPoint = x.m_pCountPtr->m_pPoint;
m_pCountPtr->m_count = x.m_pCountPtr->m_count; x.m_pCountPtr->m_pPoint = pRet;
x.m_pCountPtr->m_count = count;
} int user_count(){return m_pCountPtr->m_count; } T& operator *()
{
return *(m_pCountPtr->m_pT);
} T* operator ->()
{
return m_pCountPtr->m_pT;
} private:
void minusOne()
{
if (m_pCountPtr->m_count-- == )
{
delete m_pCountPtr;
m_pCountPtr = nullptr;
}
else
{
cout << "引用次数:" << m_pCountPtr->m_count << endl;
}
}
CCountPtr<T> *m_pCountPtr;
}; /*这里使用了参数包,我对此不是很熟悉,直接copy的代码*/
template<typename T, typename... Args>
inline CSmartPtr<T>
make_smart(Args&&... args)
{
return CSmartPtr<T>(new T(std::forward<Args>(args)...));
} int main()
{
int b=;
int* a=&b;
{
CSmartPtr<int> sptr1(a);
{
cout << "*sptr1: " << *sptr1 << endl;
CSmartPtr<int> sptr2 = sptr1; cout << "*sptr2: " << *sptr2 << endl; CSmartPtr<int> sptr3 = make_smart<int>();
cout << "*sptr3: " << *sptr3 << endl;
}
cout<<"sptr1.count: "<< sptr1.user_count()<<endl;
} system("pause");
return ;
}
以上为智能指针shared_ptr的实现过程,还是有很多东西要学习的。
以下为参考网站,以至于很多东西都是直接拿过来的,感谢!
https://www.cnblogs.com/QG-whz/p/4777312.html
http://www.cplusplus.com/reference/memory/unique_ptr/unique_ptr/
https://liam.page/2018/01/13/smart-pointer/
C++——智能指针unique_ptr的实现的更多相关文章
- c/c++ 智能指针 unique_ptr 使用
智能指针 unique_ptr 使用 和shared_ptr不同,可以有多个shared_ptr指向同一个内存,只能有1个unique_ptr指向某个内存.因此unique_ptr不支持普通的拷贝和赋 ...
- c++11 智能指针 unique_ptr、shared_ptr与weak_ptr
c++11 智能指针 unique_ptr.shared_ptr与weak_ptr C++11中有unique_ptr.shared_ptr与weak_ptr等智能指针(smart pointer), ...
- C++智能指针 unique_ptr
C++智能指针 unique_ptr unique_ptr 独占所指向的对象, 同一时刻只能有一个 unique_ptr 指向给定对象(通过禁止拷贝语义, 只有移动语义来实现), 定义于 memory ...
- 智能指针unique_ptr的用法
unique_ptr是独占型的智能指针,它不允许其他的智能指针共享其内部的指针,不允许通过赋值将一个unique_ptr赋值给另一个unique_ptr,如下面错误用法: std::unique_pt ...
- C++11 智能指针unique_ptr使用 -- 以排序二叉树为例
用智能指针可以简化内存管理.以树为例,如果用普通指针,通常是在插入新节点时用new,在析构函数中调用delete:但有了unique_ptr类型的智能指针,就不需要在析构函数中delete了,因为当u ...
- 智能指针unique_ptr
转自:https://www.cnblogs.com/DswCnblog/p/5628195.html 成员函数 (1) get 获得内部对象的指针, 由于已经重载了()方法, 因此和直接使用对象是一 ...
- 智能指针 unique_ptr
unique_ptr 不共享它的指针.它无法复制到其他 unique_ptr,无法通过值传递到函数,也无法用于需要副本的任何标准模板库 (STL) 算法. 1.不能进行复制构造和赋值操作(unique ...
- 智能指针unique_ptr记录
unique_ptr 对对象独有管理,无法复制,共享,值传递,可以使用move语义来转移控制权. std::default_delete<int> d; std::unique_ptr&l ...
- 第20课 unique_ptr独占型智能指针
一. unique_ptr的基本用法 (一)初始化方式 1. 直接初始化:unique<T> myPtr(new T); //ok.但不能通过隐式转换来构造,如unique<T&g ...
随机推荐
- JAVAEE 第六周
JSF 生命周期: FacesServlet 充当用户和 JSF 应用程序之间的纽带.它在明确限定的 JSF 生命周期(规定了用户请求之间的整个事件流)的范围内工作. 1. 当JSF页面上的一个事 ...
- js初学
1.学习一门编程语言需要记住知识点: 1.关键字. 2.标识符. 3.注释. 4.运算符. 5.常量和变量 . 6.语句. 7.函数 ...
- 重新复习~ 为了重新找工作 - > XMLHttpRequest2.0 Jsonp nodeType 节点 webpack基本搭建 闭包的一句话总结
XMLHttpRequest2.0 1.可以设置超时 (xhr.timeout = 1000; ontimeout()函数) 2.支持FormData对象管理表单数据(new FormData 方法: ...
- JAVA 平时作业二
编写一个 Java 应用程序,统计数组{1,3,4,7,2,1,1,5,2,5,7,2,1,1,3},统 计显示每种数字其出现的次数以及出现最多和最少次数的数字 public class Number ...
- 常用的数组函数-S
header('content-type:text/html;charset=utf-8'); //声明一个数组 $arr=['one'=>'aaa','two'=>'bbb','thre ...
- MySQL数据库语句
一 . 常用mysql命令行命令 1 .启动MYSQL服务 net start mysql 停止MYSQL服务 net stop mysql 2 . netstat –na | ...
- Blinn-Phong模型
最近在看基础光照模型,比较感兴趣的是高光反射模型,有下列两种: 1.Phong模型 R = 2*N(dot(N, L)) - L specular = lightColor * SpecularCol ...
- 【转】Android-Input 键盘设备
https://source.android.com/devices/input/keyboard-devices 键盘设备 Android 支持各种键盘设备,包括特殊功能小键盘(音量和电源控制),紧 ...
- CentOS6.5 安装vncserver实现图形化访问
一. 安装gnome图形化桌面 #yum groupinstall -y "X Window System" #yum groupinstall -y "Desktop& ...
- ENVI5.3 影像重采样 和 tiff 保存
输入---之前用envi4.5处理后的2013分类影像---输出重采样的影像 直接在工具栏搜索 resize data---出来对话框, 这里有几种方法----sample line 指的行列号,可以 ...