智能指针
智能指针的使用以及原理:
智能指针的思想:RAll
RAll是一种利用对象声明周期来控制程序资源的一种技术。它可以在对象构造时获取资源,在对象析构时候释放资源,完全不用用户自己释放,当然也解决了用原生态指针的缺陷。
RAll思想的好处:
1.不用自己显示释放申请的资源,用户不用考虑什么术后该释放资源,将这些交给编译器即可。
2.用这种方法,对象所需的资源在其生命周期内始终保持有效。
下面我们用RAll思想来设计一个智能指针:
template<class T>
class Sptr
{
public:
Sptr(T* ptr=nullptr)
:_ptr(ptr)
{
}
~Sptr()
{
if (_ptr)
{
delete _ptr;
_ptr = nullptr;
}
}
T* operator->()const//智能指针也是指针,也要有指针的基本功能
{
return _ptr;
}
T& operator*()const
{
return *_ptr;
}
private:
T* _ptr;
};
上述是一个基本的智能指针。我们可以发现,因为涉及资源管理,所以当用一个指针去拷贝另一个指针时,就会产生浅拷贝,并且不能用深拷贝来解决。
因此综上所述我们可以得出在所有不同的智能指针中:
1.因为RAll思想,资源可以自动释放
2.定义的智能指针类中,必须有普通指针类似的行为:operator*()以及operator->()
3.解决浅拷贝
auto_ptr
为了解决浅拷贝的问题,在C++98中,提供了auto_ptr智能指针。
注:所有C++库中智能指针都定义在memory这个头文件中。
通过使用auto_ptr我们可以发现,其解决浅拷贝方式是:资源转移,也就是所拷贝结束后,前面的指针置为空。只有后面的指针有地址。
下面我们来实现这个智能指针:
//模拟智能指针
namespace My
{
template<class T>
class auto_ptr
{
public:
auto_ptr(T* ptr = nullptr)
:_ptr(ptr)
{
}
~auto_ptr()
{
if (_ptr)
{
delete _ptr;
_ptr = nullptr;
}
}
T* operator->()const//智能指针也是指针,也要有指针的基本功能
{
return _ptr;
}
T& operator*()const
{
return *_ptr;
}
auto_ptr(auto_ptr<T>& p)//此处参数前面不能用const,因为要将前面的指针值为空
: _ptr(p._ptr)
{
p._ptr = nullptr;
}
auto_ptr<T>& operator=(auto_ptr<T>& p)
{
if (this != &p)
{
if (_ptr)
delete _ptr;
_ptr = p._ptr;//赋值
p._ptr = nullptr;//断开前面指针
}
return *this;
}
private:
T* _ptr;
};
}
上述就是auto_ptr的模拟实现。但是我们发现因为把前面的指针已经与资源断开练联系,所以无法操作自己的资源。这也就是资源转移的缺陷,所以这种类型的auto_ptr在很多情况下不能用。
在解决浅拷贝时,除了上述资源转移的方法,还有一种方法也可以解决浅拷贝——加一个判定条件,让资源只释放一次。
我们来实现一下这个代码:
//模拟第二种解决办法
namespace My
{
template<class T>
class