前面讲到auto_ptr有个很大的缺陷就是所有权的转移,就是一个对象的内存块只能被一个智能指针对象所拥有.但我们有些时候希望共用那个内存块.于是C++ 11标准中有了shared_ptr这样的智能指针,顾名思义,有个shared表明共享嘛.所以shared_ptr类型的智能指针可以做为STL容器的元素
下面我们来瞧瞧shared_ptr具体是咋实现的.相较auto_ptr有下面几个不同的地方:
1.引进了一个计数器shared_count,用来表示当前有多少个智能指针对象共享指针指向的内存块
2.析构函数中不是直接释放指针对应的内存块,如果shared_count大于1则不释放内存只是将引用计数减1,只是计数等于1时释放内存
3.复制构造与赋值操作符只是提供一般意义上的复制功能,并且将引用计数加1.
shared_ptr实现代码
#include<iostream>
#include<memory>
using namespace std;
/*
class for counted reference semantics
deletes the object to which it refers when the last CountedPtr
that refers to it is destroyed
*/
template <class T>
class CountedPtr
{
private:
T* ptr; // pointer to the value
long* count; // shared number of owners
public:
//initialize pointer with existing pointer
//-requires that the pointer p is a return value of new
explicit CountedPtr(T* p = 0)
: ptr(p), count(new long(1))
{
}
//copy pointer (one more owner)
CountedPtr(const CountedPtr& p) throw()
: ptr(p.ptr), count(p.count)
{
++*count;
}
//destructor (delete value if this was the last owner)
~CountedPtr() throw()
{
dispose();
}
//assignment (unshare old and share new value)
CountedPtr & operator= (CountedPtr & p) throw()
{
if (this != &p)
{
dispose();
ptr = p.ptr;
count = p.count;
++*count;
}
return *this;
}
//access the value to which the pointer refers
T& operator*() const throw()
{
return *ptr;
}
T* operator->() const throw()
{
return ptr;
}
private:
void dispose()
{
if (--*count == 0)
{
delete count;
delete ptr;
}
}
};
class A
{
public:
A()
{
cout << "A CONSTRUCT!" << endl;
}
~A()
{
cout << "A DESSTRUCT!" << endl;
}
CountedPtr<A> m_ptr;
};
class CLeader;
class CMember;
class CLeader
{
public:
CLeader()
{
cout << "CLeader::CLeader()" << endl;
}
~CLeader()
{
cout << "CLeader:;~CLeader() " << endl;
}
CountedPtr<CMember> member;
};
class CMember
{
public:
CMember()
{
cout << "CMember::CMember()" << endl;
}
~CMember()
{
cout << "CMember::~CMember() " << endl;
}
CountedPtr<CLeader> leader;
};
void TestSharedPtrCrossReference()
{
cout << "TestCrossReference<<<" << endl;
CountedPtr<CLeader> ptrleader(new CLeader);
CountedPtr<CMember> ptrmember(new CMember);
ptrleader->member = ptrmember;
ptrmember->leader = ptrleader;
}
int main()
{
//循环引用,引发内存泄露
CountedPtr<A> ap1(new A());
ap1->m_ptr = ap1;
//循环引用,引发内存泄露
TestSharedPtrCrossReference();
CountedPtr<int>ap2(new int(1));
CountedPtr<int>ap3(ap2);//ap2任然拥有所有权
return 0;
}