1. 起初,我最直观的设计想法,直接设计一个类:包含全部要素(对象,指针计数)。然后提供出去。
 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的实现的更多相关文章

  1. c/c++ 智能指针 unique_ptr 使用

    智能指针 unique_ptr 使用 和shared_ptr不同,可以有多个shared_ptr指向同一个内存,只能有1个unique_ptr指向某个内存.因此unique_ptr不支持普通的拷贝和赋 ...

  2. 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), ...

  3. C++智能指针 unique_ptr

    C++智能指针 unique_ptr unique_ptr 独占所指向的对象, 同一时刻只能有一个 unique_ptr 指向给定对象(通过禁止拷贝语义, 只有移动语义来实现), 定义于 memory ...

  4. 智能指针unique_ptr的用法

    unique_ptr是独占型的智能指针,它不允许其他的智能指针共享其内部的指针,不允许通过赋值将一个unique_ptr赋值给另一个unique_ptr,如下面错误用法: std::unique_pt ...

  5. C++11 智能指针unique_ptr使用 -- 以排序二叉树为例

    用智能指针可以简化内存管理.以树为例,如果用普通指针,通常是在插入新节点时用new,在析构函数中调用delete:但有了unique_ptr类型的智能指针,就不需要在析构函数中delete了,因为当u ...

  6. 智能指针unique_ptr

    转自:https://www.cnblogs.com/DswCnblog/p/5628195.html 成员函数 (1) get 获得内部对象的指针, 由于已经重载了()方法, 因此和直接使用对象是一 ...

  7. 智能指针 unique_ptr

    unique_ptr 不共享它的指针.它无法复制到其他 unique_ptr,无法通过值传递到函数,也无法用于需要副本的任何标准模板库 (STL) 算法. 1.不能进行复制构造和赋值操作(unique ...

  8. 智能指针unique_ptr记录

    unique_ptr 对对象独有管理,无法复制,共享,值传递,可以使用move语义来转移控制权. std::default_delete<int> d; std::unique_ptr&l ...

  9. 第20课 unique_ptr独占型智能指针

    一. unique_ptr的基本用法 (一)初始化方式 1. 直接初始化:unique<T> myPtr(new T);  //ok.但不能通过隐式转换来构造,如unique<T&g ...

随机推荐

  1. php留言板程序

    =================== 先创建note.php <html><head><title>PHP留言本</title></head&g ...

  2. Java虚拟机学习-Java内存区域(一)

    Java虚拟机内存划分为以下几个区域: 1.方法区:方法区是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息.常量.静态变量.即时编译器编译后的代码等数据.虽然Java虚拟机规范把方法区描述为 ...

  3. python学习笔记:2.python基础

    4.27 01,pycharm 安装使用. 011,昨日内容回顾.     编译型:         将代码一次性全部编译成二进制,然后运行.         优点:执行效率高.         缺点 ...

  4. SSL backend error when using OpenSSL pycurl install error

    centos7 pip install pycurl 错误 pip uninstall pycurl export PYCURL_SSL_LIBRARY=nss pip install pycurl ...

  5. web前端之Javascript---function函数

    ---恢复内容开始--- js 支持两种函数:一类是语言内部的函数(如eval() ),另一类是自己创建的. 在 JavaScript 函数内部声明的变量(使用 var)是局部变量,所以只能在函数内部 ...

  6. nginx 多域名指向多个根目录配置,设置自定义请求头 proxy_set_header,ssl 证书安装配置

    1.nginx.conf 配置文件引入子配置文件 include vhost-server/*.conf;  关键在 server_name  不同域名执行不同的根 user root; #user ...

  7. python flask 如何修改默认端口号

    场景:按照github文档上启动一个flask的app,默认是用5000端口,如果5000端口被占用,启动失败. 样例代码: from flask import Flask app = Flask(_ ...

  8. 运行caffe自带的mnist实例教程

    运行caffe自带的mnist实例教程 本文结合几篇博文总结下来的,附上其中一篇原博文链接以供参考:http://blog.sina.com.cn/s/blog_168effc7e0102xjr1.h ...

  9. mybatis(2)--配置mybatis实现连接数据库查询

    1.新建项目 2.在src下创建一个xml文件 比如这xml文件名为 mybatis.xml 一下为初始xml文件代码 <?xml version="1.0" encodin ...

  10. 【转】Android-Input 触控笔

    https://source.android.com/devices/accessories/stylus 触控笔 Android 6.0 及更高版本支持蓝牙 (BT).蓝牙低功耗 (BTLE) 或 ...