智能指针之 unique_ptr

时间:2023-03-09 02:04:38
智能指针之 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