1 内存泄漏问题
-
动态申请堆空间,用完后不归还
-
C++ 语言中没有垃圾回收机制
-
指针无法控制所指堆空间的生命周期
-
示例1:内存泄漏
-
Demo
#include <iostream> #include <string> using namespace std; // 测试类 class Test { int i; public: Test(int i) { this->i = i; } int value() { return i; } ~Test() { } }; int main() { for(int i = 0; i < 5; i++) { Test* p = new Test(i); cout << p->value() << endl; } return 0; }
-
编译运行
0 1 2 3 4
-
存在内存泄漏:24 行定义的局部变量
p
在for
循环结束后会自动销毁,但其所指向的堆空间并没有消失,那么就没有人没有使用这块堆空间,造成内存泄漏
-
-
需要什么?
- 需要一个特殊的指针
- 指针生命周期结束时主动释放堆空间 ---> 避免内存空间忘记释放的问题
- 一片堆空间最多只能由一个指针标识 ---> 避免一块内存空间多次释放的问题
- 杜绝指针运算和指针比较 ---> 避免指针越界,防止野指针的出现
2 智能指针
-
解决方案
- 重载指针特征操作符(
->
和*
) - 只能通过类的成员函数重载
- 重载函数不能使用参数
- 只能定义一个重载函数
- 重载指针特征操作符(
-
示例2:智能指针
-
Demo
#include <iostream> #include <string> using namespace std; // 测试类 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; } Pointer(const Pointer& obj) { // 不需要释放成员变量所指向堆空间,因为是构造函数,mp还是一个野指针,不能delete 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; } }; int main() { Pointer p1 = new Test(0); cout << p1->value() << endl; Pointer p2 = p1; cout << p1.isNull() << endl; cout << p2->value() << endl; return 0; }
-
编译运行
Test(int i) 0 1 0 ~Test()
-
-
智能指针使用规则:只能用来指向堆空间中的对象或者变量