C++笔记-auto_ptr&unique_ptr&shared_ptr&shared_ptr基本用法
Posted IT1995
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++笔记-auto_ptr&unique_ptr&shared_ptr&shared_ptr基本用法相关的知识,希望对你有一定的参考价值。
前一篇博文的笔记是:C++文档阅读笔记-Smart Pointers in C++ and How to Use Them
这里Geek大体介绍了智能指针的基本,但感觉不是很具体,在此补充下例子,方便以后查阅。
本次例子主要是使用这4种类型的智能指针。
代码如下:
#include <QCoreApplication>
#include <QDebug>
#include <memory>
#include <iostream>
using namespace::std;
class Rectangle
public:
Rectangle(int l, int b)
length = l;
breadth = b;
~Rectangle()
qDebug() << "~Rectangle() called";
int area()
return length * breadth;
private:
int breadth;
int length;
;
void autoPtr()
qDebug() << "void autoPtr()";
auto_ptr<Rectangle> ptr1(new Rectangle(10, 5));
qDebug() << "ptr1->area() : " << ptr1->area();
auto_ptr<Rectangle> ptr2(ptr1);
qDebug() << "ptr2->area() : " << ptr2->area();
void uniquePtr()
qDebug() << "void uniquePtr()";
unique_ptr<Rectangle> ptr1(new Rectangle(10, 2));
qDebug() << "ptr1->area() : " << ptr1->area();
unique_ptr<Rectangle> ptr2 = move(ptr1);
qDebug() << "ptr2->area() : " << ptr2->area();
void sharedPtr()
qDebug() << "void sharedPtr()";
shared_ptr<Rectangle> ptr1(new Rectangle(1, 2));
qDebug() << "ptr1->area() : " << ptr1->area();
qDebug() << "ptr1.use_count() : " << ptr1.use_count();
shared_ptr<Rectangle> ptr2(ptr1);
qDebug() << "ptr2->area() : " << ptr2->area();
qDebug() << "ptr2.use_count() : " << ptr2.use_count();
qDebug() << "ptr1.use_count() : " << ptr1.use_count();
void weakPtr()
qDebug() << "void weakPtr()";
shared_ptr<Rectangle> ptr1(new Rectangle(100, 1));
qDebug() << "ptr1->area() : " << ptr1->area();
qDebug() << "ptr1.use_count() : " << ptr1.use_count();
weak_ptr<Rectangle> ptr2 = ptr1;
qDebug() << "ptr1.use_count() : " << ptr1.use_count();
qDebug() << "ptr2.lock()->area() : " << ptr2.lock()->area();
int main(int argc, char *argv[])
QCoreApplication a(argc, argv);
autoPtr();
qDebug() << "";
uniquePtr();
qDebug() << "";
sharedPtr();
qDebug() << "";
weakPtr();
return a.exec();
运行截图如下:
这里就简单来看下auto_ptr,我这里是windows平台:
#if _HAS_AUTO_PTR_ETC
// TEMPLATE CLASS auto_ptr
template<class _Ty>
class auto_ptr;
template<class _Ty>
struct auto_ptr_ref
// proxy reference for auto_ptr copying
explicit auto_ptr_ref(_Ty *_Right)
: _Ref(_Right)
// construct from generic pointer to auto_ptr ptr
_Ty *_Ref; // generic pointer to auto_ptr ptr
;
template<class _Ty>
class auto_ptr
// wrap an object pointer to ensure destruction
public:
typedef auto_ptr<_Ty> _Myt;
typedef _Ty element_type;
explicit auto_ptr(_Ty *_Ptr = 0) _THROW0()
: _Myptr(_Ptr)
// construct from object pointer
auto_ptr(_Myt& _Right) _THROW0()
: _Myptr(_Right.release())
// construct by assuming pointer from _Right auto_ptr
auto_ptr(auto_ptr_ref<_Ty> _Right) _THROW0()
// construct by assuming pointer from _Right auto_ptr_ref
_Ty *_Ptr = _Right._Ref;
_Right._Ref = 0; // release old
_Myptr = _Ptr; // reset this
template<class _Other>
operator auto_ptr<_Other>() _THROW0()
// convert to compatible auto_ptr
return (auto_ptr<_Other>(*this));
template<class _Other>
operator auto_ptr_ref<_Other>() _THROW0()
// convert to compatible auto_ptr_ref
_Other *_Cvtptr = _Myptr; // test implicit conversion
auto_ptr_ref<_Other> _Ans(_Cvtptr);
_Myptr = 0; // pass ownership to auto_ptr_ref
return (_Ans);
template<class _Other>
_Myt& operator=(auto_ptr<_Other>& _Right) _THROW0()
// assign compatible _Right (assume pointer)
reset(_Right.release());
return (*this);
template<class _Other>
auto_ptr(auto_ptr<_Other>& _Right) _THROW0()
: _Myptr(_Right.release())
// construct by assuming pointer from _Right
_Myt& operator=(_Myt& _Right) _THROW0()
// assign compatible _Right (assume pointer)
reset(_Right.release());
return (*this);
_Myt& operator=(auto_ptr_ref<_Ty> _Right) _THROW0()
// assign compatible _Right._Ref (assume pointer)
_Ty *_Ptr = _Right._Ref;
_Right._Ref = 0; // release old
reset(_Ptr); // set new
return (*this);
~auto_ptr() _NOEXCEPT
// destroy the object
delete _Myptr;
_Ty& operator*() const _THROW0()
// return designated value
#if _ITERATOR_DEBUG_LEVEL == 2
if (_Myptr == 0)
_DEBUG_ERROR("auto_ptr not dereferencable");
#endif /* _ITERATOR_DEBUG_LEVEL == 2 */
return (*get());
_Ty *operator->() const _THROW0()
// return pointer to class object
#if _ITERATOR_DEBUG_LEVEL == 2
if (_Myptr == 0)
_DEBUG_ERROR("auto_ptr not dereferencable");
#endif /* _ITERATOR_DEBUG_LEVEL == 2 */
return (get());
_Ty *get() const _THROW0()
// return wrapped pointer
return (_Myptr);
_Ty *release() _THROW0()
// return wrapped pointer and give up ownership
_Ty *_Tmp = _Myptr;
_Myptr = 0;
return (_Tmp);
void reset(_Ty *_Ptr = 0)
// destroy designated object and store new pointer
if (_Ptr != _Myptr)
delete _Myptr;
_Myptr = _Ptr;
private:
_Ty *_Myptr; // the wrapped object pointer
;
#endif /* _HAS_AUTO_PTR_ETC */
_STD_END
这里以auto_ptr为例,研究2个问题:
①auto_ptr是如何调用传给他的原始指针;
②auto_ptr是如何实现原始指针的析构。
从中可以看到:
其实auto_ptr就是一封装类,他将传入的指针放到了_Ty中,命名为_Myptr。
构造函数要将需要变智能的指针传进来,给_Myptr赋值。
这里可以看到,但调用->这个符号后,他先看_Myptr有无值,如果有就调用get()方法。
如果是要使用*这个负荷:
就会传*get()过来,这里差不多就可以猜到,这个get()方法,返回的就是_Myptr
从中可以看到,的确,get方法返回被包裹的指针。第一个问题就研究完了,
下面来看第二个问题,他是如何实现资源的释放的。
看到这里想必都已经明白了,auto_ptr一般是在栈区进行创建,当栈区生命周期结束后,调用其自己的析构函数,而他自己的析构函数里面对_Myptr进行了delete。
以上是关于C++笔记-auto_ptr&unique_ptr&shared_ptr&shared_ptr基本用法的主要内容,如果未能解决你的问题,请参考以下文章
C++笔记-auto_ptr&unique_ptr&shared_ptr&shared_ptr基本用法
深入了解C++ (15) | 源码分析auto_ptr & unique_ptr 设计