STL中的智能指针不能用于引用计数,但是其优点是
指针所有权自动转移和指针自动删除技术.
auto_ptr会在复制构造时,将原指针自动删除,将使用权交给其复制的对象.
例子:
//源码
template<class T>
class auto_ptr{
public:
explicit auto_ptr(T* p=0):_M_ptr(p){} //构造函数,注意使用了explicit修饰
auto_ptr(auto_ptr<class U> & rhs) : _M_ptr(rhs.release()){} //复制构造函数, rhs交出使用权,自身删除.
//......
private:
T *p;
}
class CTest{
public:
void print()
{
std::cout<<"Hello World"<<endl;
}
}
int main()
{
std::auto_ptr<CTest> ptr;
std::auto_ptr<CTest> ptr2(ptr);
ptr->print(); //Error, 该指针已经被释放了.
return 0;
}
值得注意的是, 一般的智能指针具有引用计数的功能.下面将具体介绍智能指针的实现方法.
方法一: 将目标类定义为指针类的友员类, 目标类自身维护引用计数;
方法二: 如下, 指针类内部维护引用计数, 但是需要重载*, ->, =, &符号.
template <class T>
class SmartPtr
{
public:
SmartPtr(T *p = 0): ptr(p), pUse(new size_t
(1)) { }
SmartPtr(const SmartPtr& src): ptr(src.ptr), pUse(src.pUse) {
++*pUse;
}
SmartPtr& operator= (const SmartPtr& rhs) {
// self-assigning is also right
++*rhs.pUse;
decrUse(); //注意这里需要将自身的引用计数减1
ptr = rhs.ptr;
pUse = rhs.pUse;
return *this;
}
T *operator->() {
if (ptr)
return ptr;
throw std::runtime_error("access through NULL pointer");
}
const T *operator->() const {
if (ptr)
return ptr;
throw std::runtime_error("access through NULL pointer");
}
T &operator*() {
if (ptr)
return *ptr;
throw std::runtime_error("dereference of NULL pointer");
}
const T &operator*() const {
if (ptr)
return *ptr;
throw std::runtime_error("dereference of NULL pointer");
}
~SmartPtr() {
decrUse();
#ifdef TEST_SMARTPTR
std::cout<<"SmartPtr: Destructor"<<std::endl; // for testing
#endif
}
private:
void decrUse() {
if (--*pUse == 0) {
delete ptr;
delete pUse;
}
}
T *ptr;
size_t
*pUse;
};