这里所说的都不是STL里的东西,只是简单的模仿一下。
程序里一般我们将一些常用的,不是临时的对象放在堆上,堆的空间是比较大的。但是如果我们只是不停的动态申请但是忘记在不使用的时候归还就会造成内存泄露。有时候我们也会因为同一块内存空间被多个指针指向,在释放时造成多次释放的问题。为了避免这些,所以我们试着来创建一个特殊的指针。
1在生命周期结束的时候直接释放掉堆里的内存空间
2且这个指针指向的内存不会再被别的指针指向这里。
3为了防止出现野指针和2的情况出现,所以我们不允许对指针做运算和比较。
这就是我们的“智能指针”,我们可以创建一个类,类里面有一个成员变量,是一个指针,这样如果就满足了上述的第三条,应为此时是我们创建的一个对象,不满足那些操作符。我们使用构造函数的参数列表让使用者将动态分配的地址传入,在函数体中赋值给成员变量,这样就满足了上述的第二条。最后我们在析构函数释放这个动态申请的内存,这样就满足了第三条。最后为了让这个对象满足指针的取址操作,我们要重载->和*这两个操作符。还有一点,因为这里的成员是指针,所以我们的拷贝构造函数和=的重载必须实现深拷贝,而且只能让内存只属于某个指针,c++里虽然不允许多次释放一个堆内存,但是可以多次delete内容为NULL的指针,所以我们要使用这一特性。
切记,我们这里必须是堆上的内存。“智能指针”只适用于堆空间。
class Test
{
int i;
public:
Test(int i)
{
cout << "Test(int i)" << endl;
this->i = i;
}
int value()
{
return i;
}
~Test()
{
cout << "~Test()" << endl;
}
};
class Pointer
{
Test* mp;
public:
Pointer(Test* p = NULL)
{
mp = p;
}
/*因为要满足第2条,所以一块内存只能被一个指针指向,所以右值的成员变量要设置为NULL*/
Pointer(const Pointer& obj)
{
mp = obj.mp;
const_cast<Pointer&>(obj).mp = NULL;
}
Pointer& operator = (const Pointer& obj)
{
if( this != &obj )
{
delete mp;
mp = obj.mp;
const_cast<Pointer&>(obj).mp = NULL;
}
return *this;
}
Test* operator -> ()
{
return mp;
}
Test& operator * ()
{
return *mp;
}
bool isNull()
{
return (mp == NULL);
}
~Pointer()
{
delete mp;
}
};