智能指针之 unique_ptr
对于动态申请的内存,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的更多相关文章
- 深入学习c++--智能指针(三) unique_ptr
1. 几种智能指针 1. auto_ptr: c++11中推荐不使用他(放弃) 2. shared_ptr: 拥有共享对象所有权语义的智能指针 3. unique_ptr: 拥有独有对象所有权语义的智 ...
- 智能指针(三):unique_ptr使用简介
我们知道auto_ptr通过复制构造或者通过=赋值后,原来的auto_ptr对象就报废了.所有权转移到新的对象中去了.而通过shared_ptr可以让多个智能指针对象同时拥有某一块内存的访问权.但假如 ...
- [转] 智能指针(三):unique_ptr使用简介
PS: 1. auto_ptr太不安全,可能多个auto_ptr指向一个对象,出现重复释放的问题 2. unique_ptr解决了这个问题,不允许拷贝构造函数和赋值操作符,但是!它支持移动构造函数,通 ...
- 智能指针std::unique_ptr
std::unique_ptr 1.特性 1) 任意时刻只能由一个unique_ptr指向某个对象,指针销毁时,指向的对象也会被删除(通过内置删除器,通过调用析构函数实现删除对象) 2)禁止拷贝和赋值 ...
- C++11智能指针 share_ptr,unique_ptr,weak_ptr用法
0x01 智能指针简介 所谓智能指针(smart pointer)就是智能/自动化的管理指针所指向的动态资源的释放.它是存储指向动态分配(堆)对象指针的类,用于生存期控制,能够确保自动正确的销毁动 ...
- c++智能指针(unique_ptr 、shared_ptr、weak_ptr、auto_ptr)
一.前序 什么是智能指针? ——是一个类,用来存储指针(指向动态分配对象也就是堆中对象的的指针). c++的内存管理是让很多人头疼的事,当我们写一个new语句时,一般就会立即把delete语句直接也写 ...
- C++2.0新特性(八)——<Smart Pointer(智能指针)之unique_ptr>
一.概念介绍 unique_ptr它是一种在异常发生时可帮助避免资源泄露的smart pointer,实现了独占式拥有的概念,意味着它可确保一个对象和其他相应资源在同一时间只被一个pointer拥有, ...
- C++11智能指针(unique_ptr、shared_ptr、weak_ptr)(转)
原文地址:https://blog.csdn.net/king_way/article/details/95536938
- C++11 unique_ptr智能指针详解
在<C++11 shared_ptr智能指针>的基础上,本节继续讲解 C++11 标准提供的另一种智能指针,即 unique_ptr 智能指针. 作为智能指针的一种,unique_ptr ...
随机推荐
- 面向对象中Object常用属性总结
学完Object属性,自己总结一些常用是Object常用属性. Object.prototype:属性表示Object的原型对象. 属性: Object.prototype.constructor:特 ...
- 前端学习之jquery
前端学习之jquery 1. 什么是jQuery对象? jQuery对象就是通过jQuery包装DOM对象后产生的对象.jQuery对象是jQuery独有的.如果一个对象是jQuery对象,那么它 ...
- NetCore2.0技术文章目录
记录NetCore2.0的学习和工作,理解对与错不重要,重要的是,我飘~~~过 ------------------------------------------------------------ ...
- js字符串操作总结
字符方法 <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf- ...
- Spring(5)——Spring 和数据库编程
传统 JDBC 回顾 JDBC 我们一定不陌生,刚开始学习的时候,我们写过很多很多重复的模板代码: public Student getOne(int id) { String sql = " ...
- maven项目添加db2的jar包
安装完DB2后,SQLLIB文件夹下的java目录下有对应的jar包,我的SQLLIB文件夹位置在 D:\Program Files\IBM\SQLLIB\java 处. 此目录直接添加到CLASSP ...
- app 下载更新 file-downloader 文件下载库的简单介绍和使用
app 下载更新 file-downloader 文件下载库的简单介绍和使用 今天介绍一个下载库:file-downloader 文件下载库 说明: * 本文内容来自原 file-downloader ...
- 手写java虚拟机(一)——搭建环境
毕业设计打算做一个java虚拟机,首先要对java虚拟机有一个简单的了解(jvm).目前市面上有众多的jvm,如sun公司的HotSpot VM.Classic VM,IBM公司的J9 VM等等,这里 ...
- 机器学习:scipy和sklearn中普通最小二乘法与多项式回归的使用对
相关内容连接: 机器学习:Python中如何使用最小二乘法(以下简称文一) 机器学习:形如抛物线的散点图在python和R中的非线性回归拟合方法(以下简称文二) 有些内容已经在上面两篇博文中提到了,所 ...
- 从零开始系列之vue全家桶(3)安装使用vuex
什么是vuex? vuex:Vue提供的状态管理工具,用于同一管理我们项目中各种数据的交互和重用,存储我们需要用到数据对象. 即data中属性同时有一个或几个组件同时使用,就是data中共用的属性. ...