智能指針 shared_ptr:
https://blog.csdn.net/u012501459/article/details/48229399
C++11中引入了智能指針的概念。使用普通指針,容易造成堆內存泄露(忘記釋放),二次釋放,使用智能指針能更好的管理堆內存。
- 構造函數中創建類的新對象時,初始化引用計數爲1;
- 拷貝構造函數複製指針,並使相應的引用計數增加1;
- 賦值操作減少左操作數所值對象的引用計數,增加右操作數所指對象的引用計數;
-
析構函數使引用計數減少1,並且當引用計數爲0時,釋放指針說指向的對象;
定製刪除器:
#include<iostream>
#include<memory>
using namespace std;
int main(){
shared_ptr<int> sp1(new int(10));
cout<<*sp1<<endl;
*sp1 = 20;
cout<<*sp1<<endl;
return 0;
}
我們動態申請的內存,構造時完成初始化,析構時通過delete來釋放沒有任何問題。但是文件指針可能就掛了。
#include<iostream>
#include<memory>
using namespace std;
int main(){
shared_ptr<FILE> sp1(fopen("test.txt","w"));
//如果不進行任何特殊處理,則程序崩潰!
return 0;
}
因此,shared_ptr提供了刪除器功能,我們可以通過定製刪除器,來對特定的資源進行回收。
#include<iostream>
#include<memory>
using namespace std;
//仿函數
struct Fclose{
void operator()(void *ptr){
fclose((FILE*)ptr);
cout<<"不用擔心,shared_ptr已經通過調用我關閉了文件!"<<endl;
}
};
int main(){
//我們通過傳入仿函數,來完成對文件指針的清理
shared_ptr<FILE> sp1(fopen("test.txt","w"),Fclose());
return 0;
}
Ref_ptr類:
//使用int*指針初始化ptr,注意必須要放在初始化列表中
Ref_ptr(int * i):ptr(new Referenced(i))
{
}
//拷貝構造函數,又有一個變量指向了這塊內存
Ref_ptr(const Ref_ptr & rhs)
{
ptr=rhs.ptr;//將右操作數的引用計數對象賦值給左操作數
ptr->ref();//將它們的應用計數加1
}
Ref_ptr r1=new int(4); //調用構造函數
Ref_ptr r2=r1; //調用拷貝構造函數
//賦值操作符,右操作數的引用計數要減1,左操作數的引用計數要加1
Ref_ptr & operator=(const Ref_ptr & rhs)
{
if(&rhs==this)
return *this;
if(ptr->unref()==0)//賦值操作符,首先將當前類的引用計數減1,因爲現在指向它的指針少了一個。
{
cout<<"delete Ref_ptr"<<endl;
delete ptr;
}
ptr=rhs.ptr; //將右操作數的引用計數賦值給當前對象
ptr->ref(); //引用計數加1
return *this;
}
//析構函數,引用計數要減1,如果減爲0,刪除這塊內存
~Ref_ptr()
{
if(ptr->unref()==0)
{
cout<<"delete Ref_ptr"<<endl;
delete ptr;
}
}
Referenced類:
//初始化這個類,引用計數設爲1,並且將p指向傳入的地址
Referenced(int * pi)
{
refCount=1;
p=pi;
}
//引用計數加1
int ref()
{
return ++refCount;
}
//引用計數減1
int unref()
{
return --refCount;
}
//析構函數,釋放掉內存
~Referenced()
{
cout<<"delete referenced"<<endl;
delete p;
}
好處:
- 智能指針能夠幫助我們處理資源泄露問題;
- 它也能夠幫我們處理空懸指針的問題;
- 它還能夠幫我們處理比較隱晦的由異常造成的資源泄露。
循環引用:
#include <memory>
class B;
class A
{
public:
~A()
{
printf("delete A");
}
std::shared_ptr < B >
m_b;
};
class B
{
public:
~B()
{
printf("delete B");
}
std::shared_ptr < A >
m_a;
};
int main()
{
std::shared_ptr<A> a(new A); //new出來的A的引用計數此時爲1
std::shared_ptr<B> b(new B); //new出來的B的引用計數此時爲1
a->m_b = b; //B的引用計數增加爲2
b->m_a = a; //A的引用計數增加爲2
}