1.内存泄漏
2.野指针
3.访问越界
boost智能指针(RAII资源获取及初始化 在构造函数中初始化 在析构函数中释放资源)
class RAIIClass
{
public:
RAIIClass()
{
InitializeCriticalSection(&cs);
EnterCriticalSection(&cs);
}
~RAIIClass()
{
LeaveCriticalSection(&cs);
DestoryCriticalSection(&cs);
}
private:
CriticalSection cs;
};
所有的智能指针都有一个explict构造函数,以指针为参数
将基本类型的指针封装为类对象指针(这个类肯定为模板,以适应不同的类型的) ,在析构函数中使用delete语句删除指针指向的空间 (代理模式)
对于编译器来说 此时的智能指针相当于一个栈对象 在栈对象生命期即将结束时,通过析构函数释放它管理的对内存。
在了解智能指针之前首先谈一下explict关键字、
c++中的explicit关键字
只能用于修饰只有一个参数的类的构造函数,默认为隐式的
//必须显示按照这种方式才能调用成功
explicit CString(int size)
{
//do something
}
CString cs = 10 // error
//转换构造函数
CString(int size)
{
//do something
}
CString cs = 10 // ok
shared_ptr和intrusive_ptr
在用法上都支持获取管理权 共享管理权等等操作 唯一不同的是intrusive_ptr中参数的指针必须实现
AddRef()和Release()等增加和减少引用计数的功能
templtae<class T>
class shared_ptr
{
shared_ptr(); //指向空指针的智能指针 引用计数为0,get()=NULL 访问智能指针包含的指针可以使用get()
template<class Y>explict shared_ptr(Y *p);
//为什么模板的类型与构造函数中的参数类型不一致?
//说明类型T和Y之间一定存在继承的关系或类型一致(即支持多态)
template<class Y,class D>explict shared_ptr(Y* p,D fun);
//例如文件的打开之后的关闭操作 D实际上为一个仿函数对象
boost::shared_ptr<fopen("",mode),fclose>
};
智能指针的判空
由于智能指针为一个对象 所以if(智能指针对象)永远为真 要判断智能指针的裸指针为空 if(智能指针对象.get())
智能指针的实现auto_ptr
template<class T>
class auto_ptr
{
explicit auto_ptr(T* p = 0);
//...
}
double * pd = new double;
auto_ptr<double> apd = pd;
为什么摒弃auto_ptr?
auto_ptr<string> ap1 = new string("auto_ptr");
auto_ptr<string> ap2;
ap2 = ap1;
//避免operator=中浅复制的问题
解决方案1.定义operator=函数,实现深复制
2.限制特定的类型只能有一个智能指针对象 ,unique_ptr
3.在智能指针的基础上,增加引用计数 ,为0时才会调用delete ,share_ptr
使用shared_ptr智能指针需要注意的地方
1.shared_ptr多次引用同一内存导致数据崩溃
Foo *fp = new Foo();
boost::shared_ptr<Foo> shared_ptr1(fp);
boost::shared_ptr<Foo> shared_ptr2(fp);
解决方案
1.RAII
2.使用boost的make_shared模板函数
2.shared_ptr循环引用导致内存泄露
class son;
class parent
{
boost::shared_ptr<son> son_ptr;
};
class son
{
boost::shared_ptr<parent> parent_ptr;
};
boost::shared_ptr<parent> father(new parent());
boost::shared_ptr<son> child(new son());
father->son_ptr = child;
child->parent_ptr = father;
解决方案
使用weak_ptr
在实际工作中,为了避免内存泄漏,使用了shared_ptr来接管com组件的方法,利用工厂的方式创建不同的组件 而shared_ptr在使用的过程中必须将引用计数初始化的时候为1