1.永恒的话题
- 内存泄漏(臭名昭著的Bug)
- 动态申请堆空间,用完后不归还
- C++语言中没有垃圾回收的机制
- 指针无法控制所指堆空间的生命周
2.编程实验
- 内存泄漏
#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); // 在每轮循环结束p被销毁,所指向的堆空间没有被释放
cout << p->value() << endl;
}
system("pause");
return 0;
}
3.深度的思考
- 我们需要什么
- 需要一个特殊的指针
- 指针生命周期结束时主动释放堆空间
- 一片堆空间最多只能由一个指针标识
- 杜绝指针运算和指针比较
4.智能指针分析
- 解决方案:创建智能指针类
- 重载指针特征操作符(->和*)
- 只能通过类的成员函数重载
- 重载函数不能使用参数
- 只能定义—个重载函数
#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)// /初始化构造函数,置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不是野指针了,所以可以释放。
mp = obj.mp;
const_cast<Pointer &>(obj).mp = NULL; // 强制取消obj的只读属性
}
return *this; // 返回引用可以连续赋值,不会生成临时变量。
}
// 重载 ->
Test* operator->() // 不能使用参数,所以也就只能定义一个重载函数
{
return mp;
}
// 重载 *
Test& operator*()
{
return *mp;
}
bool isNULL()
{
return (mp == NULL);
}
~Pointer()
{
delete mp; // 智能指针被析构时, 同时删除其所管理的Test类的对象。
}
};
int main()
{
Pointer p1 = new Test(100); // 智能指针指向从堆空间申请来的内存地址,这个内存地址指向类
cout << p1->value() << endl; // 如果对象被释放,则会调用析构函数,打印出信息
Pointer p2 = p1; // 调用拷贝构造函数。p2接管了p1所指向的堆空间,保证每次只能由一个智能指针指向堆空间。
cout << p1.isNULL() << endl; // 1,为NULL p1指向NULL了, 不再指向原来的堆空间
cout << p2->value() << endl; // p2接管了p1所指堆空间
system("pause");
return 0;
}
- 运行结果:
- 智能指针实现,使用:智能指针类保存要被管理对象的指针,重载=操作符,实现拷贝构造函数,实现指针操作符,析构函数里面释放被管理对象的指针,使用时无需手动释放,对象结束自动析构。
- 智能指针的使用军规:只能用来指向堆空间中的对象或者变量
5.小结
- 指针特征操作符( -> 和 * )可以被重载
- 重载指针特征符能够使用对象代替指针
- 智能指针只能用于指向堆空间中的内存(不能用于栈上的)
- 智能指针的意义在于最大程度的避免内存问题