目录
1.为什么需要智能指针?
2.内存泄漏
3.智能指针的使用及原理
4.C++11和boost中智能指针的关系
5.RAII扩展学习
这里有一个代码,分析一下其中有什么会导致内存泄漏的地方
int Div()
{
int a, b;
cin >> a >> b;
if (b == 0)
throw invalid_argument("除0错误");
return a / b;
}
void func()
{
int* p1 = new int;
int* p2 = new int;
cout << Div() << endl;
delete p1;
delete p2;
}
int main()
{
try
{
func();
}
catch(exception& e)
{
cout << e.what() << endl;
}
return 0;
}
template
class SmartPtr {
public:
SmartPtr(T* ptr = nullptr)
:_ptr(ptr)
{}
~SmartPtr()
{
if (_ptr)
delete _ptr;
}
private:
T* ptr;
};
然后接着改造一开始的func代码
void func()
{
SmartPtr p1(new int);
SmartPtr p2(new int);
cout << Div() << endl;
}
此时p1和p2已经交给了samrtPtr的对象来管理,当该函数栈帧结束时会自动调用析构函数释放这两个指针,防止内存泄漏。
emplate
class SmartPtr {
public:
SmartPtr(T* ptr = nullptr)
:_ptr(ptr)
{
}
~SmartPtr()
{
if (_ptr)
delete _ptr;
}
T& operator*()
{
return *_ptr;
}
T* operator->()
{
return _ptr;
}
private:
T* ptr;
};
struct StuId
{
int _id;
string _name;
int _num;
};
int main()
{
SmartPtr p1(new int);
*p1 = 20;
SmartPtr p2(new StuId);
p2->_id = 1;
p2->_name = "张三";
p2->_num = 119;
return 0;
}
autoptr.h
namespace myspace
{
template
class Autoptr
{
public:
Autoptr(T* ptr = nullptr)
:_ptr(ptr)
{}
Autoptr(Autoptr& p)
:_ptr(p._ptr)
{
// 管理权转移
p._ptr = nullptr;
}
Autoptr& operator=(Autoptr& ap)
{
if (*this != &ap)
{
if (_ptr)
delete _ptr;
// 转移ap中资源到当前对象中
_ptr = ap._ptr;
ap._ptr = NULL;
}
return *this;
}
~Autoptr()
{
if (_ptr)
{
cout << "delete:" << _ptr << endl;
delete _ptr;
}
}
// 像指针一样使用
T& operator*()
{
return *_ptr;
}
T* operator->()
{
return _ptr;
}
private:
T* _ptr;
};
}
main.cpp
int main()
{
myspace::Autoptr p1(new int(10));
myspace::Autoptr p2 = p1;
// // sp1悬空
*p2 = 10;
cout << *p2 << endl;
cout << *p1 << endl;
return 0;
}
由于p1悬空还进行访问操作会导致程序崩溃,结论:auto_ptr是一个失败设计,很多公司明确要求不能使用auto_ptr
template
class UniquePtr
{
public:
UniquePtr(T* ptr=nullptr)
:_ptr(ptr)
{}
~UniquePtr()
{
if (_ptr)
{
cout << "delete:" << _ptr << endl;
delete _ptr;
}
}
// 像指针一样使用
T& operator*()
{
return *_ptr;
}
T* operator->()
{
return _ptr;
}
UniquePtr(const UniquePtr& sp) = delete;
UniquePtr& operator=(const UniquePtr& sp) = delete;
private:
T* _ptr;
};
}
template
class SharePtr
{
public:
SharePtr(T* ptr=nullptr)
:_ptr(ptr)
,_count(new int(1))
{}
SharePtr(const SharePtr& sp)
:_ptr(sp._ptr)
, _count(sp._count)
{
++(*_count);
}
template
SharePtr(T* ptr, D del)
:_ptr(ptr)
, _count(new int(1))
, _del(del)
{}
SharePtr& operator=(const SharePtr& sp)
{
if(sp._ptr!=_ptr)
{
relese();
_ptr = sp._ptr;
_count = sp._count;
++(*_count);
}
return *this;
}
void relese()
{
--(*_count);
if (*_count == 0 && _ptr)
{
cout << "delete:" << _ptr << endl;
_del (_ptr);
delete _count;
_ptr = nullptr;
_count = nullptr;
}
}
int use_count() const
{
return *_count;
}
T* get() const
{
return _ptr;
}
~SharePtr()
{
relese();
}
private:
T* _ptr;
int* _count;
function _del = [](T* ptr) {delete ptr; };
};
}
其中还引入了一个定制删除器,可以从外部传入可调用函数释放资源。