智能指针之 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 ...
随机推荐
- python/Django(增、删、改、查)操作
python/Django(增.删.改.查)操作 我们要通过pycharm中的Django模块连接MySQL数据库进行对数据的操作. 一.创建Django项目(每创建一个项目都要进行以下设置) 1.如 ...
- python Mysql 库表
Mysql 库表 创建 学生信息库表 学生成绩 库表
- SpringMVC(二):RequestMapping修饰类、指定请求方式、请求参数或请求头、支持Ant路径
@RequestMapping用来映射请求:RequestMapping可以修饰方法外,还可以修饰类 1)SpringMVC使用@RequestMapping注解为控制指定可以处理哪些URL请求: 2 ...
- c#获取网络时间并同步本地时间
通过TCP形式来获取NTP时间.主要代码如下: [DllImport("kernel32.dll")] private static extern bool SetLocalTim ...
- 微信小程序:wx.request之post请求后端无法获取数据的问题
前言:小程序的开发中总是踩到各种坑,看文档也不知所云: 例如当我们在写微信小程序接口时,method请求方式有POST和GET两种,为了数据安全,我们会偏向于使用POST请求方式访问服务器端: 问题: ...
- NLog日志管理工具(转)
一.通过VS建立一个控制台应用程序. 二.打开程序包管理器控制台.具体操作如下:[工具]>[库程序包管理器]>[程序包管理器控制台]. 三.在程序包管理器控制台下输入命令:Install- ...
- rf常用关键字总结
上传文件choose file 用法:choose file 元素定位 文件路径\\文件名 此处注意:复制的路径是/,需全部替换成\\ 清除Clear Element Tex ...
- java利用poi来读取execl表格返回对象
利用poi来读取execl表格,返回一个对象(可能有点不完善,但是应该能满足平常的所用),用到了反射等等; 使用的jar包有: commons-collections4-4.1.jar poi-3.1 ...
- svg从入门到装逼(一)
svg文件是基于xml的矢量图,而canvas是基于html和js的位图.关于两者的比较,在粗就不赘述了. 1. 首先来上一个svg的基本结构: <?xml version="1.0 ...
- Redis常用命令--Hashes
Hash是由键值对组成的map.Hashes的底层是通过字典实现的.一个哈希表里面可以有多个哈希表节点.而每个哈希节点就保存了字典中的一个键值对. 字典是一种用于保存键和值对的抽象数据结构.字典里的每 ...