对于动态申请的内存,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. Java8新特性第1章(Lambda表达式)

    在介绍Lambda表达式之前,我们先来看只有单个方法的Interface(通常我们称之为回调接口): public interface OnClickListener { void onClick(V ...

  2. 基于Verilog HDL的超前进位全加器设计

    通常我们所使用的加法器一般是串行进位,将从输入的ci逐位进位地传递到最高位的进位输出co,由于电路是有延迟的,这样的长途旅行是需要时间的,所以为了加快加法器的运算,引入了超前进位全加器. 全加器的两个 ...

  3. 复习HTML+CSS(2)

    n  项目符号嵌套编号思路 标签的内容(文本.项目符号.表格.图片等)必须放在最底层标记中. n  图片标记(行内元素,单边标记) l  语法:<img 属性 = "值"&g ...

  4. Codeforces Round #426 (Div. 2)

    http://codeforces.com/contest/834 A. The Useless Toy 题意: <,>,^,v这4个箭头符号,每一个都可以通过其他及其本身逆时针或者顺时针 ...

  5. javascript中的事件类型

    表单事件 submit reset click change focus blur input window事件 load DomContentLoaded readyStatechange unlo ...

  6. [LeetCode] Max Area of Island 岛的最大面积

    Given a non-empty 2D array grid of 0's and 1's, an island is a group of 1's (representing land) conn ...

  7. [LeetCode] Equal Tree Partition 划分等价树

    Given a binary tree with n nodes, your task is to check if it's possible to partition the tree to tw ...

  8. pdf如何转换为word文档

    我们经常会遇到需要将PDF转换为WORD文档,对于我来讲,有些PDF没有目录,看起来非常不方便,于是就特别想转成WORD,然后增加目录,想看某一节内容时,快速查找. 这里我总结了一些方法,后续也会不断 ...

  9. [NOIp 2017]列队

    Description Sylvia 是一个热爱学习的女孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. Sylvia 所在的方阵中有$n \times m$名学生, ...

  10. 计蒜客NOIP模拟赛D2T2 直线的交点

    伦伦刚刚在高中学习了解析几何,学会了计算两条直线的交点.这天,老师给她布置了一道作业.在平面上有 nnn 条直线,他们之间有若干交点.给定一对平板(两条平行的直线),问这有多少对直线,他们的交点在这一 ...