1,本文介绍智能指针,为了避免内存泄漏问题;
2,永恒的话题,内存泄漏(臭名昭著的 Bug ):
1,动态申请堆空间,用完后不归还;
2,C++ 语言中没有垃圾回收的机制;
1,Java、C# 语言中都引入了垃圾回收机制,定期检测内存,发现没有使用,则回收;
2,垃圾回收机制可以很好的避免内存泄漏;
3,C++ 中的动态内存申请和归还完全依赖开发者,所以必然会出错;
1,大型软件公司采用编码流程和代码规范,来解决包括内存泄漏的问题;
2,提交代码需要小组内部人员审核代码是否准许了编码流程和代码规范,效率低下,也包括熟读代码规范;
3,效率低下,产品上市受影响;
3,指针无法控制所指堆空间的生命周期;
1,操作动态内存空间的时候,都是基于指针,而指针就是一个变量,指针可以指向动态空间,但是却不能够控制动态内存空间的生命周期;
2,也就是指针和动态内存空间没有必然联系,指针变量销毁了,动态内存空间还可以存在;
3,上述两点就是本质问题;
3,内存泄漏编程实验:
1,main.cpp 文件:
1 #include <iostream> 2 #include <string> 3 4 using namespace std; 5 6 class Test 7 { 8 int i; 9 public: 10 Test(int i) 11 { 12 this->i = i; 13 } 14 int value() 15 { 16 return i; 17 } 18 ~Test() 19 { 20 } 21 }; 22 23 int main() 24 { 25 for(int i=0; i<5; i++) 26 { 27 Test* p = new Test(i); //p 指向堆空间,但是下面没有归还,同时 p 是一个局部变量,for 循环结束后就销毁了,但是所指向的堆空间并没有销毁,没人可以使用这片空间,内存就泄漏了; 28 29 cout << p->value() << endl; 30 } 31 32 return 0; 33 }
4,深度分析,我们需要什么:
1,需要一个特殊的指针;
1,智能指针对象,通过类的普通构造函数完成;
2,指针生命周期结束时主动释放堆空间;
1,这是最主要的一点,通过类的析构函数完成;
3,一片堆空间最多只能由一个指针标识;
1,避免多次释放内存,通过拷贝构造函数和赋值操作符完成;
4,杜绝指针运算和指针比较;
1,杜绝指针运算可以避免指针越界和野指针;
2,上面的第三个需求都满足了,指针比较就没有意义了;
3,通过不重载类的运算符自行完成;
5,智能指针分析:
1,解决方案:
1,重载指针特征操作符(-> 和 *);
1,通过操作符重载模拟指针的行为;
2,定义一个对象,让这个对象通过操作符重载模拟真正的指针行为;
3,-> 和 * 是 C++ 中的操作符,所以我们必然可以重载;
4,遵循下面三点重载规则;
2,只能通过类的成员函数重载;
1,能切仅能通过类的成员函数重载;
3,重载函数不能使用参数;
1,两者都是单目运算符;
4,只能定义一个重载函数;
1,和第三点是一件事;
2,通过指针的特征操作符来使用对象替代指针,这个对象 就称为智能指针, 或者通过类对象模拟指针的行为,这个类对象称为智能指针;
3,智能指针编程实验:
1,main.cpp 文件:
1 #include <iostream> 2 #include <string> 3 4 using namespace std; 5 6 class Te