一、内存泄漏-永恒的话题
- 动态申请堆空间,用完后不归还
- C++ 语言中没有垃圾回收的机制
- 指针无法控制所指堆空间的生命周期
下面看一段内存泄漏的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | #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; } |
输出结果如下:
二、深度思考
- 需要一个特殊的指针
- 指针生命周期结束时主动释放堆空间
- 一片堆空间最多只能由一个指针标识
- 杜绝指针运算和指针比较
三、智能指针分析
解决方案
- 重载指针特征操作符( -> 和 * )
- 只能通过类的成员函数重载
- 重载函数不能使用参数
- 只能定义一个重载函数
下面看一段智能指针的使用示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | #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 = 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; } |
输出结果如下:
注意这两行代码的含义,
1 2 | mp = obj.mp; const_cast <Pointer&>(obj).mp = NULL; |
表明当前对象的成员指针指向初始化对象的成员指针所对应的堆空间,这就两个智能指针对象指向了同一片堆空间,然后 const_cast<Pointer&>(obj).mp = NULL; 表明初始化对象把自己管理的堆空间交给当前对象。这就完成了前面说的“一片堆空间最多只能由一个指针标识”。
茶狐在线提示:智能指针使用的军规:只能用来指向堆空间中的对象或者变量
四、小结
- 指针特征操作符( -> 和 * )可以被重载
- 重载指针特征符能够使用对象代替指针
- 智能指针只能用于指向堆空间中的内存
- 智能指针的意义在于最大程度的避免内存问题