在使用指针的时候容易产生内存泄漏(在申请后没有释放)
-动态申请堆空间,用完不归还。这样就导致越来越多的堆空间不能够被使用到。
-C++语言中没有垃圾回收的机制
-指针无法控制所指堆空间的声明周期(但是类的构析函数可以)。
例如如下代码:
#include <iostream>
using namespace std;
class testPointer
{
int i;
public:
int getValue()
{
return i;
}
testPointer(int i)//构造函数
{
this->i = i;//赋值
cout << "Test(int i)" <<endl;
}
~testPointer()//构析函数
{
cout << "~Test()" <<endl;
}
};
int main()
{
for(int i = 0 ; i< 10 ;i++)
{
testPointer *p = new testPointer(i);
cout << p->getValue() <<endl;
}
return 0;
}
上面代码在堆空间动态申请 testPointer 类,但是没有使用delete 关键字来释放testPointer 这样将导致内存泄漏。
代码运行结果:
Test(int i)
0
Test(int i)
1
Test(int i)
2
Test(int i)
3
Test(int i)
4
Test(int i)
5
Test(int i)
6
Test(int i)
7
Test(int i)
8
Test(int i)
9
所以我们需要一个智能指针。(实现一个指针类,重载 -> 与* 指针操作符)
1、在指针生命周期结束后主动释放空间。
2、一片堆空间最多智能由一个指针标识。
3、杜绝掉指针运算与指针比较。
#include <iostream>
using namespace std;
class testPointer
{
int i;
public:
int getValue()
{
return i;
}
testPointer(int i)//构造函数
{
this->i = i;//赋值
cout << "Test(int i)" <<endl;
}
~testPointer()//构析函数
{
cout << "~Test()" <<endl;
}
};
class pointer
{
testPointer* mp; //定义一个 testPointer指针
public:
pointer(testPointer* p = NULL)//构造函数
{
mp = p;
}
pointer(const pointer& obj)//拷贝构造函数
{
mp = obj.mp; //移交所有权,满足一段堆空间由一个指针标识
const_cast<pointer&>(obj).mp = NULL;//去除obj只读属性
}
pointer& operator = (const pointer& obj)//重载 = 号操作符
{
if( this != &obj )//避免出现 = 两边一致现象 ,自赋值
{
delete mp;
mp = obj.mp;
const_cast<pointer&>(obj).mp = NULL;
}
return *this;
}
testPointer* operator -> () //重载指针中的 ->操作符
{
return mp;
}
testPointer& operator * ()//重载指针中的 * 操作符
{
return *mp;
}
bool isNull()//当前指针是否为空
{
return (mp == NULL);
}
~ pointer()
//指针构析函数。
{
delete mp;
}
};
int main()
{
pointer p1 = new testPointer(10);
cout << p1->getValue() <<endl;
pointer p2 = p1;//通过重载的 = 号操作符 实现一片堆空间最多智能由一个指针标识
cout << p1.isNull()<<endl;
cout << p2->getValue()<<endl;
return 0;
}
最终使用构析函数实现:在指针生命周期结束后主动释放空间。
使用拷贝构造函数实现:一片堆空间最多智能由一个指针标识。
由于没有实现 运算与 指针比较。所以:杜绝掉指针运算与指针比较。
运行结果:
Test(int i)
10
1
10
~Test()