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. scrapy_redis项目配置

    一.创建普通scrapy项目 二.spiders爬虫文件中修改项 import scrapy from XX.items import XXItem import json # ----1 导入类 f ...

  2. DevExpress ASP.NET Core Controls 2019发展蓝图(No.2)

    本文主要为大家介绍DevExpress ASP.NET Core Controls 2019年的官方发展蓝图,更多精彩内容欢迎持续收藏关注哦~ [DevExpress ASP.NET Controls ...

  3. Android 问题列表

    25. Touch 事件传递机制 26. 点击事件设置监听的几种方式 27. Hander 的原理 28. Thread 和HandThread 的区别 29. AsyncTask 简介 30. As ...

  4. 零基础学习JavaSE(一)

    一.开发环境安装配置 1.1 安装jdk jdk下载地址:http://www.oracle.com/technetwork/java/javase/downloads/index.html 下载后安 ...

  5. 18.Canny边缘检测

    Canny边缘检测算法以Canny的名字命名,其中Canny的目标是找到一个最优的边缘检测算法,其有三种衡量标准: 低错误率:标识出尽可能多的实际边缘,同时尽可能的减少噪声产生的误报 高定位性:标识出 ...

  6. MySQL从本地向数据库导入数据

    本文来自:https://www.cnblogs.com/lettuce-u/p/10715795.html(自己收藏看) 在localhost中准备好了一个test数据库和一个pet表: mysql ...

  7. letCode-1

    日前,使用暴力法破解此题,认为这是很简单的算法,但是所有人都能想出来的算法,凭什么优秀?所以在看到了大神“Grandyang”的博客上精妙的解法,实在是认为自己需要修炼,在此写在这里是为了做笔记,加深 ...

  8. pytest自动化2:测试用例setup和teardown

    前言: pytest支持函数和类两种用例方式,针对每种情况都有不同的代码 pytest用例运行级别 模块级(setup_module/teardown_module)开始于模块始末,全局的 函数级(s ...

  9. linux运维工作内容及岗位要求

    什么是Linux?大家日常使用电脑听歌.打游戏娱乐或处理日常工作时,接触到最多的就是Windows操作系统,电脑如果不安装Windows系统是无法进行娱乐和工作的,所有的软件程序都必须运行在操作系统之 ...

  10. Javascript学习二---DOM元素操作

    Javascript 主要包括:JS的语法,DOM和BOM操作以及ECMAScript语法. 1 获取元素的方法 获取元素方法: 通过ID:document.getElementById(); 一个 ...