标签:list may inter 部分 get oid highlight raii 代码

/*************************************************************************
> File Name: AutoPtr.cc
> Author: tp
> Mail:
> Created Time: Sun 13 May 2018 05:08:41 PM CST
************************************************************************/
#include <iostream>
using namespace std;
struct A
{
int age;
string name;
A(string na, int a = 0)
:age(a), name(na)
{ }
};
template <class T>
class AutoPtr
{
public:
AutoPtr(T* ptr)
:_ptr(ptr) { }
T& operator*()
{
return *_ptr;
}
T* operator->()
{
return _ptr;
}
//ap2( ap1)
AutoPtr(AutoPtr<T>& a) //防止多次析构,ap2直接夺取管理权,ap1._ptr置空
:_ptr(a._ptr)
{
a._ptr = NULL;
}
//ap2 = ap1
AutoPtr<T>& operator=(AutoPtr<T>& a)
{
if(this != &a)
{
delete _ptr;
_ptr = a._ptr;
a._ptr = NULL;
}
return *this;
}
~AutoPtr( )
{
cout<<"AutoPtr帮助析构\n";
delete _ptr;
}
protected:
T* _ptr;
};
int main( void)
{
AutoPtr<int> ap1(new int(20));
cout<<++(*ap1)<<endl;
AutoPtr<A> ap2(new A("napom"));
cout<<ap2->name<<endl;
return 0;
}
这里这两个地方,是需要弄清楚的

然后,看一手结果:

/*************************************************************************
> File Name: ScopedPtr.cc
> Author: tp
> Mail:
> Created Time: Sun 13 May 2018 06:02:24 PM CST
************************************************************************/
#include <iostream>
using namespace std;
struct A
{
int age;
string name;
A(string na, int a = 0)
:age(a), name( na)
{ }
};
template <class T>
class ScopedPtr
{
public:
ScopedPtr(T* ptr)
:_ptr(ptr) { }
T& operator*()
{
return *_ptr;
}
T* operator->()
{
return _ptr;
}
~ScopedPtr( )
{
cout<<"AutoPtr析构\n";
delete _ptr;
}
protected:
ScopedPtr(ScopedPtr<T>& a);
ScopedPtr<T>& operator=( ScopedPtr<T>& a);
T* _ptr;
};
上面的scoped_ptr用于处理单个的对象,而new/delete和new[]/delete[]底层实现机制又是不同的(delete[]头部多开4字节,具体可戳这里)对于new[]出来的多个对象,boost又提供了一个scoped_array版本的智能指针用来管理对象数组,用法和scoped_ptr类似。同样的,上面的auto_ptr也有一个auto_array版本。
scoped_ptr的就好似“你强任你强”,我不给你机会施展,看你怎么夺权管理。这种做法虽然达到了上面的目的。但是这种暴力的思想却带来了新的问题。。由于scoped智能指针独享所有权,当我们真真需要复制智能指针时,需求便满足不了了。如此我们再引入一个更完善智能指针指针,专门用于处理复制,参数传递的情况。这便是如下的shared智能指针。
> File Name: sharedPtr.cc
> Author: tp
> Mail:
> Created Time: Sun 13 May 2018 06:11:02 PM CST
************************************************************************/
#include <iostream>
using namespace std;
struct A
{
int age;
string name;
A(string na, int a = 0)
:age(a), name( na)
{ }
};
//引用计数版本
template <class T>
class SharedPtr
{
public:
SharedPtr( T* ptr)
:_ptr(ptr)
,_pCount( new int(1))
{ }
T* operator->( )
{
return _ptr;
}
T& operator*( )
{
return *_ptr;
}
SharedPtr(const SharedPtr<T>& sp) //加上const
:_ptr(sp._ptr)
,_pCount(sp._pCount)
{
++(*_pCount);
}
SharedPtr<T>& operator=(const SharedPtr<T>& sp)
{
if(this != &sp)
{
Release( );
_ptr = sp._ptr;
_pCount = sp._pCount;
++(*_pCount);
}
return *this;
}
void Release( )
{
if(--(*_pCount) == 0)
{
cout<<"释放空间"<<endl;
delete _ptr;
delete _pCount;
_ptr = NULL;
_pCount = NULL;
}
}
~SharedPtr()
{
//cout<<"析构调用"<<endl;
Release( );
}
protected:
T* _ptr;
int* _pCount;
};
int main( void)
{
SharedPtr<A> sp1(new A("gene"));
cout<<sp1->name<<endl;
SharedPtr<A> sp2(sp1);
cout<<sp2->name<<endl;
SharedPtr<A> sp3(new A("codfish"));
sp3 = sp2;
cout<<sp3->name<<endl;
return 0;
}

struct Node
{
// shared_ptr<Node> _prev;
// shared_ptr<Node> _next;
weak_ptr<Node> _prev;
weak_ptr<Node> _next;
// Node()
// :_prev(NULL)
// ,_next(NULL)
// {}
~Node()
{
cout<<"~Node"<<endl;
}
};
void TestCycleReference( void)
{
shared_ptr<Node> cur( new Node);
shared_ptr<Node> next( new Node);
cur->_next = next;
next->_prev = cur;
cout<<"cur.count:"<<cur.use_count()<<endl;
cout<<"next.count:"<<next.use_count()<<endl;
}

1. 拷贝构造
1 constexpr weak_ptr() noexcept; 2 3 weak_ptr (const weak_ptr& x) noexcept; 4 template <class U> weak_ptr (const weak_ptr<U>& x) noexcept; 5 6 template <class U> weak_ptr (const shared_ptr<U>& x) noexcept;
如果一个参数x被传递,而x不是空的,那么弱ptr对象就变成了拥有的x组的一部分,在没有所有权本身的情况下(并且不增加它的使用数量),就可以访问该对象的资产。
如果x是空的,或者如果没有参数传递,构造的弱ptr是空的。
如果x是一个别名,弱ptr保存了所有的数据和存储的指针。
2.operator=重载
1 weak_ptr& operator= (const weak_ptr& x) noexcept; 2 template <class U> weak_ptr& operator= (const weak_ptr<U>& x) noexcept; 3 4 template <class U> weak_ptr& operator= (const shared_ptr<U>& x) noexcept
对象成为拥有的x组的一部分,允许对该对象的资源进行访问,直到过期,而不需要获得所有权本身(并且不增加其引用计数)。
如果x是空的,构造的弱ptr也是空的。
如果x是一个别名,弱ptr保存了所有的数据和存储的指针。
shared_ptr对象可以直接分配给弱ptr对象,但是为了将弱ptr对象分配给sharedptr,它应该使用成员锁(lock)来完成。
包括上面成员,它一共有这些成员

可参考cpulsplus官网:http://www.cplusplus.com/reference/memory/weak_ptr/
在前面用到了的shared_ptr的时候,如果够仔细,你可能注意C++11没有shared_array版本的智能指针,也就是说,对于new[]开出的对象数组,C++11好像没有相应的处理办法了? 当然,这是不可能的。C++11对于此,实际上站在了一个更高的角度来处理。虽然在boost中有_array版本的智能指针管理new[]出来的对象数组,但是实际中还有malloc,fopen..等方式打开资源,单纯的用delete关闭资源显然是力不从心的。所以对此,C++11提供用一个叫删除器的东西来帮助释放资源,它由程序员自己去定置。它的实现其实就是定义一个类出来,然后在类中重载了operator() 在该函数当中进行相应释放资源操作(由于重载了operator(),类就拥有函数的使用特性和功能.所以将这样的类也叫做仿函数)。如我们shared_ptr<int> sp(new int[2]),就可以实现一个这样的类
template<class T> struct DeleteArray { void operator()(T* ptr) { delete[] ptr; } } ;
然后可以DeleteArray da定置一个删除器da了 。随后,前面定义智能指针相应改成shared_ptr<int> sp(new int[2], da)即可。
其实它原理也比较简单,为了更方便剖析,我们这里来对上面自定义SharePtr改造,让它支持定置删除功能。
template<class T>
struct DelArr
{
void operator()(T* ptr)
{
cout<<"delete[ ]"<<endl;
delete[] ptr;
}
};
template <class T, class Del= DelArr<T> > //为模板参数添加默认值
class SharedPtr
{
public:
SharedPtr( T* ptr)
:_ptr(ptr)
,_pCount( new int(1))
{ }
T* operator->( )
{
return _ptr;
}
T& operator*( )
{
return *_ptr;
}
SharedPtr(const SharedPtr<T>& sp) //加上const
:_ptr(sp._ptr)
,_pCount(sp._pCount)
{
++(*_pCount);
}
SharedPtr<T>& operator=(const SharedPtr<T>& sp)
{
if(this != &sp)
{
Release( );
_ptr = sp._ptr;
_pCount = sp._pCount;
++(*_pCount);
}
return *this;
}
void Release( )
{
if(--(*_pCount) == 0)
{
if(_ptr)
{
cout<<"释放空间"<<endl;
//delete _ptr;
//_ptr = NULL;
//_pCount = NULL;
Del _del; //定义定置删除仿函数
_del(_ptr); //调用该仿函数
}
delete _pCount;
}
}
~SharedPtr()
{
cout<<"析构调用"<<endl;
Release( );
}
protected:
T* _ptr;
int* _pCount;
};
void TestSharedPtr()
{
//SharedPtr<A, DelArr<A> > sp(new A[2]);
SharedPtr<int, DelArr<int> >sp1(new int[2]);
}

1 class Free 2 { 3 public: 4 void operator()(void* ptr) 5 { 6 free(ptr); 7 } 8 }; 9 struct FClose 10 { 11 void operator()(void* fp) 12 { 13 fclose((FILE*)fp); 14 } 15 }; 16 vod Test() 17 { 18 shared_ptr<void> sp1(malloc(sizeof(int)*3), Free()); 19 shared_ptr<FILE> sp2(fopen("test.txt", "r"), FClose()); 20 }
不过为了平常使用智能指针能更高效的使用,最后小结一下
·在可以使用 boost 库的场合下,拒绝使用 std::auto_ptr,因为其不仅不符合 C++ 编程思想。
·在确定对象无需共享的情况下,使用 boost::scoped_ptr。
·在对象需要共享的情况下,使用 boost::shared_ptr。
·在需要访问 boost::shared_ptr 对象,而又不想改变其引用计数的情况下(循环引用)使用boost::weak_ptr。
标签:list may inter 部分 get oid highlight raii 代码
原文地址:https://www.cnblogs.com/tp-16b/p/9033370.html