对于动态申请的内存, 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(5));
- return 0;
- }
具体实现代码如下, 没有对动态对象数组及 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 0;
- }
执行代码, 打印如下:
- [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
来源: https://www.cnblogs.com/blog-yejy/p/8972858.html