在使用指针的时候容易产生内存泄漏(在申请后没有释放)
-动态申请堆空间,用完不归还。这样就导致越来越多的堆空间不能够被使用到。
-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()