对于动态申请的内存,C++语言为我们提供了new和delete运算符, 而没有像java一样,提供一个完整的GC机制,因此对于我们申请的动态内存,我们需要时刻记得释放,且不能重复释放,释放后不能再去使用...  因此在使用时造成很多不便,且容易出现很多问题,一旦出问题就造成core dump,程序直接挂掉 , 这个时候,智能指针的优势就体现出来了,智能指针符合RAII原则,资源获取就是初始化,在对象析构时,将资源进行释放,对动态内存做到一个比较好的管理

  unique_ptr 持有对对象的独有权—两个unique_ptr不能指向一个对象,不能进行复制操作只能进行移动操作

  unique_ptr拥有所有auto_ptr的功能,且unique_ptr通过将复制构造和赋值操作符私有化,将对象的所有权独有,很好的将auto_ptr的安全问题给规避掉了,unique_ptr的其他特点包括:1.提供删除器释放对象,允许用户自定义删除器 2.添加了对象数组的偏特化实现,new[],delete[] 3.使用C++ 11的右值引用特性,实现所有权转移 std::move()

  本次实现,将unique_ptr的基本接口进行了实现,基本包括了unique_ptr的功能  (编译平台:Linux centos 7.0 编译器:gcc 4.8.5 )

  使用std::unique_ptr时,需要#include <memory>头文件,具体使用代码如下(文件名:test_ptr.cpp):

 #include <memory>
#include <iostream> using namespace std; class Test
{
public:
Test()
{
cout << "construct.." << endl;
} ~Test()
{
cout << "destruct.." << endl;
}
}; void test()
{ } int main()
{
//auto_ptr
Test* p = new Test();
auto_ptr<Test> ap(p); //unique_ptr
Test* p1 = new Test();
unique_ptr<Test> up(new Test());
unique_ptr<Test> up1(move(up)); //unique_ptr<Test> up2 = up; unique_ptr<int> up3(new int()); return ;
}

  具体实现代码如下,没有对动态对象数组及std::move()进行实现,动态对象数组实现代码和这差不多,写个模板偏特化即可,至于std::move()则和成员函数release()类似,转移所有权(文件名:unique_ptr_implement.cpp):

 #include <iostream>
#include <assert.h> using namespace std; #define PTR_ASSERT(x) assert(x) template<class T>
struct defalute_deleter
{
void defalute_deleter_method()
{
cout << "deleter method..." << endl;
}
void operator()(T* ptr)
{
if(ptr != NULL)
{
cout << "default deleter....." << endl;
delete ptr;
ptr = NULL;
}
}
}; template<typename T, typename deleter = defalute_deleter<T> >
class unique_ptr
{
public:
explicit unique_ptr(T* ptr = NULL); unique_ptr(T* ptr, deleter d); ~unique_ptr(); T* get(); void reset(T* ptr = NULL); deleter& getDeleter(); T* release(); public:
T& operator*(); T* operator->(); operator bool() const; private:
unique_ptr(unique_ptr& up); unique_ptr& operator = (unique_ptr& up); private:
T* m_ptr; deleter m_deleter;
}; template<typename T, typename deleter>
unique_ptr<T, deleter>::unique_ptr(T* ptr /* = NULL */, deleter d)
{
if(ptr != NULL)
{
m_ptr = ptr;
m_deleter = d;
}
} template<typename T, typename deleter>
unique_ptr<T, deleter>::unique_ptr(T* ptr /* = NULL */)
{
if(ptr != NULL)
{
m_ptr = ptr;
}
} template<typename T, typename deleter>
unique_ptr<T, deleter>::~unique_ptr()
{
if(m_ptr != NULL)
{
m_deleter(m_ptr);
m_ptr = NULL;
}
} template<typename T, typename deleter>
T& unique_ptr<T, deleter>::operator*()
{
PTR_ASSERT(m_ptr != NULL); return *m_ptr;
} template<class T, class deleter>
T* unique_ptr<T, deleter>::operator->()
{
PTR_ASSERT(m_ptr != NULL); return m_ptr;
} template<typename T, typename deleter>
T* unique_ptr<T, deleter>::get()
{
return m_ptr;
} template<typename T, typename deleter>
void unique_ptr<T, deleter>::reset(T* ptr)
{
T* old_ptr = m_ptr;
m_ptr = ptr; if(old_ptr != NULL)
{
m_deleter(old_ptr);
old_ptr = NULL;
}
} template<typename T, typename deleter>
deleter& unique_ptr<T, deleter>::getDeleter()
{
return m_deleter;
} template<typename T, typename deleter>
T* unique_ptr<T, deleter>::release()
{
T* pTemp = m_ptr;
m_ptr = NULL; return pTemp;
} template<typename T, typename deleter>
unique_ptr<T, deleter>::operator bool() const
{
return m_ptr != NULL;
} //Test class
class Test
{
public:
Test()
{
cout << "construct.." << endl;
} ~Test()
{
cout << "destruct.." << endl;
} void method()
{
cout << "welcome Test.." << endl;
}
}; //custom deleter
template <class T>
struct custom_deleter
{
void deleter_method()
{
cout << "custom deleter method..." << endl;
} void operator()(T* ptr)
{
cout << "custom deleter... " << endl;
delete ptr;
ptr = NULL;
}
}; int main()
{
//default deleter
cout << "=======default deleter====interface test begin: ========== " << endl;
unique_ptr<Test> up(new Test()); cout << "operator ->: " << endl;
up->method(); cout << "operator *: " << endl;
(*up).method(); cout << "operator bool: " << endl;
if(up){ cout<< "obj is exit" << endl;} cout << "get: " << endl;
up.get()->method(); cout << "getDeleter: " << endl;
defalute_deleter<Test> del = up.getDeleter();
del.defalute_deleter_method(); cout << "release: " << endl;
unique_ptr<Test> up1(up.release()); //if take this, will die
//(*up).method(); cout << "reset: " << endl;
up1.reset(); //Custom deleter
cout << "=======Custom deleter====interface test begin: ========== " << endl;
custom_deleter<Test> d;
unique_ptr<Test, custom_deleter<Test> > up_custom_dele(new Test(), d); cout << "operator ->: " << endl;
up_custom_dele->method(); cout << "operator *: " << endl;
(*up_custom_dele).method(); cout << "operator bool: " << endl;
if(up_custom_dele){ cout<< "obj is exit" << endl;} cout << "get: " << endl;
up_custom_dele.get()->method(); cout << "getDeleter: " << endl;
custom_deleter<Test> custom_del = up_custom_dele.getDeleter();
custom_del.deleter_method(); cout << "release: " << endl;
unique_ptr<Test> up3(up_custom_dele.release()); //if take this, will die
//(*up_custom_dele).method(); cout << "reset: " << endl;
up3.reset(); return ;
}

  执行代码,打印如下:

 [root@localhost code]# g++ -o unique unique_ptr_implement.cpp
[root@localhost code]# ./unique
=======default deleter====interface test begin: ==========
construct..
operator ->:
welcome Test..
operator *:
welcome Test..
operator bool:
obj is exit
get:
welcome Test..
getDeleter:
deleter method...
release:
reset:
default deleter.....
destruct..
=======Custom deleter====interface test begin: ==========
construct..
operator ->:
welcome Test..
operator *:
welcome Test..
operator bool:
obj is exit
get:
welcome Test..
getDeleter:
custom deleter method...
release:
reset:
default deleter.....
destruct..
[root@localhost code]#

  从实现结果可以看出,unique_ptr保证一个动态对象只有一个unique_ptr对象所拥有,unique_ptr对象之间无法copy和赋值,只能进行动态内存对象的转移,转移时,原有的unique_ptr对象将不再拥有动态内存的访问权限,这样可以保证动态内存使用的安全性。在实现中构造函数提供了两个,一个使用默认删除器,另一个则需要我们构造时传入删除器,这样可以很好的进行资源自定义删除。 对于多个指针对象指向同一个动态内存对象,unique_ptr不适用,需使用share_ptr

智能指针之 unique_ptr的更多相关文章

  1. 深入学习c++--智能指针(三) unique_ptr

    1. 几种智能指针 1. auto_ptr: c++11中推荐不使用他(放弃) 2. shared_ptr: 拥有共享对象所有权语义的智能指针 3. unique_ptr: 拥有独有对象所有权语义的智 ...

  2. 智能指针(三):unique_ptr使用简介

    我们知道auto_ptr通过复制构造或者通过=赋值后,原来的auto_ptr对象就报废了.所有权转移到新的对象中去了.而通过shared_ptr可以让多个智能指针对象同时拥有某一块内存的访问权.但假如 ...

  3. [转] 智能指针(三):unique_ptr使用简介

    PS: 1. auto_ptr太不安全,可能多个auto_ptr指向一个对象,出现重复释放的问题 2. unique_ptr解决了这个问题,不允许拷贝构造函数和赋值操作符,但是!它支持移动构造函数,通 ...

  4. 智能指针std::unique_ptr

    std::unique_ptr 1.特性 1) 任意时刻只能由一个unique_ptr指向某个对象,指针销毁时,指向的对象也会被删除(通过内置删除器,通过调用析构函数实现删除对象) 2)禁止拷贝和赋值 ...

  5. C++11智能指针 share_ptr,unique_ptr,weak_ptr用法

    0x01  智能指针简介  所谓智能指针(smart pointer)就是智能/自动化的管理指针所指向的动态资源的释放.它是存储指向动态分配(堆)对象指针的类,用于生存期控制,能够确保自动正确的销毁动 ...

  6. c++智能指针(unique_ptr 、shared_ptr、weak_ptr、auto_ptr)

    一.前序 什么是智能指针? ——是一个类,用来存储指针(指向动态分配对象也就是堆中对象的的指针). c++的内存管理是让很多人头疼的事,当我们写一个new语句时,一般就会立即把delete语句直接也写 ...

  7. C++2.0新特性(八)——<Smart Pointer(智能指针)之unique_ptr>

    一.概念介绍 unique_ptr它是一种在异常发生时可帮助避免资源泄露的smart pointer,实现了独占式拥有的概念,意味着它可确保一个对象和其他相应资源在同一时间只被一个pointer拥有, ...

  8. C++11智能指针(unique_ptr、shared_ptr、weak_ptr)(转)

    原文地址:https://blog.csdn.net/king_way/article/details/95536938

  9. C++11 unique_ptr智能指针详解

    在<C++11 shared_ptr智能指针>的基础上,本节继续讲解 C++11 标准提供的另一种智能指针,即 unique_ptr 智能指针. 作为智能指针的一种,unique_ptr ...

随机推荐

  1. Python之几种常用模块

    模块 注意事项: 所有的模块导入都应该尽量往上写 内置模块 扩展模块 自定义模块 模块不会重复被导入 : sys.moudles 从哪儿导入模块 : sys.path import import 模块 ...

  2. Codeforces Round #441 (Div. 2, by Moscow Team Olympiad) A. Trip For Meal

    http://codeforces.com/contest/876/problem/A 题意: 一个人一天要吃n次蜂蜜,他有3个朋友,他第一次总是在一个固定的朋友家吃蜂蜜,如果说没有吃到n次,那么他就 ...

  3. Oracle:常用的一些基本操作

    表操作 查看系统中当前用户所有表: select * from user_tables;select * from user_indexs;select * from user_triggers; s ...

  4. POJ-1860 Currency Exchange---Bellman-Ford判断正环

    题目链接: https://vjudge.net/problem/POJ-1860 题目大意: 我们的城市有几个货币兑换点.让我们假设每一个点都只能兑换专门的两种货币.可以有几个点,专门从事相同货币兑 ...

  5. linux系统环境与文件权限

    默认有6个命令交互通道和一个图形界面交互通道,默认进入到的是图形界面通道 命令交互模式切换:ctrl+alt+f1---f6 图形交互界面 ctrl+alt+f7 1.图形界面交互模式 - termi ...

  6. else语句的搭配

    1.else语句搭配if 要么怎样,要么怎样 2.else语句搭配for和while 干完循环之后执行else,干不完或者break就不执行 3.else与异常处理 没有问题的话就执行else吧

  7. 原生js中实现全选和反选功能

    <!DOCTYPE html>      <html>      <head lang="en">          <meta char ...

  8. 树莓派(1)- Raspberry Pi 3B 安装系统并联网

    一.背景 昨天到手淘宝买的3B,既然买了就不能让它吃灰,动起来. 二.物料 名称 说明 硬件  树莓派3B 主体 树莓派电源 5V 2A sd卡 4G低速(推荐是16G class10),我手头只有这 ...

  9. MySQL/MariaDB触发器

    本文目录:1.创建触发器2.insert触发器3.delete触发器4.update触发器5.通过on duplicate key update分析触发器触发原理6.replace to算法验证7.查 ...

  10. [HNOI 2010]Planar

    Description 题库链接 给出 \(T\) 个 \(N\) 个节点 \(M\) 条边的无向图(无重边自环),并给出它们各自的哈密顿回路.分别判断每个图是否是平面图. \(T\leq 100,3 ...