我们知道,软件开发中的内存泄漏是最严重的Bug之一,内存泄漏主要因为如下三点引起的:
- 动态申请堆空间,用完后不归还
- C++语言中没有垃圾回收的机制
- 指针无法控制所指堆空间的生命周期
在当代的C++软件平台中的智能指针
- 指针生命周期结束时主动释放堆空间
- 一片堆空间最多只能由一个指针标识
- 杜绝指针运算和指针比较
在C++ 中智能指针的实现方案如下
- 通过类模板描述指针的行为:能够定义不同类型的指针对象
- 重载指针特征操作符(-> 和 *):利用对象模拟原生指针的行为
下边我们就使用类模板来实现一个C++智能指针
这系列的数据结构我们统一一个命名空间LMSLib,智能指针类单独建立一个头文件SmartPointer.h
#ifndef __SMARTPOINTER_H__
#define __SMARTPOINTER_H__
#include "MyObject.h"
namespace LMSLib
{
template <typename T>
class SmartPointer : public MyObject //继承自顶层父类
{
private:
T *m_pointer;
public:
SmartPointer(T* p = NULL)
{
m_pointer = p;
}
SmartPointer(const SmartPointer<T>& obj) //重新实现拷贝构造函数
{
m_pointer = obj.m_pointer;
const_cast<SmartPointer<T>&>(obj).m_pointer = NULL;
}
SmartPointer& operator = (const SmartPointer<T>& obj) //重新实现赋值构造函数
{
if (this != &obj)
{
delete m_pointer;
m_pointer = obj.m_pointer;
const_cast<SmartPointer<T>&>(obj).m_pointer = NULL;
}
return *this;
}
T* operator ->() //重载->操作符
{
return m_pointer;
}
T& operator *() //重载*操作符
{
return *(m_pointer);
}
T* get()
{
return m_pointer;
}
bool isNull()
{
return NULL == m_pointer;
}
~SmartPointer() //析构函数中释放指针
{
if (NULL != m_pointer)
{
delete m_pointer;
}
}
};
}
#endif //__SMARTPOINTER_H__
上边便实现了一个智能指针类,需要注意的是拷贝构造函数与赋值构造函数中,需要把参数obj的const属性去掉,才能将其成员指针变量赋值为NULL,下边是main函数,简单来使用下 上边定义的SmartPointer指针指针类
#include <iostream>
#include <string>
#include "SmartPointer.h"
using namespace std;
using namespace LMSLib;
class Test
{
public:
Test()
{
cout << "Test()" << endl;
}
~Test()
{
cout << "~Test()" << endl;
}
};
int main()
{
{
SmartPointer<int> p1 = new int(12); //指向一个int堆变量
cout << "(*p1) = " << (*p1) << endl;
SmartPointer<int> p2 = p1;
cout << "p1.isNull() = " << p1.isNull() << endl;
cout << "*p2.get() = " << *p2.get() << endl;
SmartPointer<Test> pt = new Test; //指向一个Test堆对象
}
system("pause");
return 0;
}
编译输出:
main函数中定义的三个智能指针 p1、p2、pt,在它们的生命周期结束后,会自动执行智能指针类中的析构函数,释放其指向的堆空间。
智能 指针的使用军规:只能用来指向堆空间的单个对象或变量
总结:
- 指针 特征操作符(->和*)可以被重载
- 重载指针特征符能够使用对象代替指针
- 智能指针只能用于指向堆空间的单个对象或变量
- 智能指针能最大程度的避免内存问题