目錄
資源管理
1.以對象管理資源
2.在管理資源類中小心copying行為
3.在資源管理類中提供對原始資源的通路
4.成對使用new和delete時要采用相同形式
5.以獨立語句将newd對象置入智能指針
資源管理
1.以對象管理資源
中心思想:把資源放進對象内,便可以依賴C++的析構函數自動調用機制確定資源被釋放。
關鍵點:
1.獲得資源後立刻放進管理對象。(Resource Acquisition Is Initialization,RAII)
2.管理對象運用析構函數確定資源被釋放。
class Lock
{
public:
explict Lock(Mutex* pm)
: mutexPtr(pm)
{
lock(mutexPtr);
}
~Lock()
{
unlock(mutexPtr);
}
private:
Mutex *mutexPtr;
}
注意事項:
1.為防止資源洩漏,請使用RAII對象,它們在構造函數中擷取資源并在析構函數中釋放資源。
2.兩個常被使用的RAII classes分别是share_ptr和auto_ptr,前者通常是較佳選擇。
2.在管理資源類中小心copying行為
如果RAII對象被複制,會發生什麼情況?
1. 禁止複制
通常允許RAII對象被複制不合理,如果需要禁止copy RAII對象,可以通過将copying操作聲明為private(繼承Uncopyable類)來禁止copy;
2. 對底層資源使用引用計數法(reference-count)
如果需要保留資源直到資源的最後一個使用者被銷毀,可實作引用計數法(shared_ptr)。
class Lock
{
public:
explict Lock(Mutex* pm)
: mutexPtr(pm , unlock)
{
lock(mutexPtr.get());
}
~Lock()
{
unlock(mutexPtr);
}
private:
std::tr1::shared_ptr<Mutex> mutexPtr;
}
std::tr1::shared_ptr允許指定删除器,當引用次數為0時調用。
3.在資源管理類中提供對原始資源的通路
#include <iostream>
#include <memory>
using namespace std;
class MyTest
{
public:
MyTest()
:n(0)
{
cout<<"MyTest()"<<endl;
}
~MyTest()
{
cout<<"~MyTest()"<<endl;
}
MyTest(const MyTest& m)
{
cout<<"copying MyTest"<<endl;
this->n = m.n;
}
void printMyTest(MyTest* m)
{
cout<<"printMyTest "<<m->n<<endl;
}
private:
int n;
};
int main()
{
//std::shared_ptr<MyTest> m_test = new MyTest();
//error: conversion from ‘MyTest*’ to non-scalar type ‘std::shared_ptr<MyTest>’ requested
std::shared_ptr<MyTest> m_test(new MyTest());
m_test->printMyTest(m_test.get());
//m_test->printMyTest(m_test);
//error: cannot convert ‘std::shared_ptr<MyTest>’ to ‘MyTest*’ ,通過get方法擷取raw指針
return 0;
}
——————————————————————————————————————————————————————————————————————
[[email protected] 15]# ./main
MyTest()
printMyTest 0
~MyTest()
4.成對使用new和delete時要采用相同形式
被删除的指針對象,是單一對象或是對象數組,處理方式不同,對象資料記憶體布局裡會多存儲一個記錄n,表示數組的大小。
(備注:不要對數組形式做typedef操作,容易産生誤操作)
std::string* mystr = new std::string();
std::string* mystrArr = new std::string[100];
delete mystr;
delete [] mystrArr;
typedef std::string strArr[10];
std::string* str = new strArr;
delete str;//出錯
delete [] str;//正确
5.以獨立語句将newd對象置入智能指針
processWidget(std::shared_ptr<Widget>(new Widget), priority());
調用processWidget需要經曆以下三個步驟:
1.調用priority()函數;
2.執行 new Widget
3.調用std::shared_ptr構造函數
C++編譯器以什麼樣的次序完成上述三個步驟存在彈性。如果執行順序是213,然後在調用priority的過程中出現異常,那new Widget傳回的指針将會遺失,不會存入std::shared_ptr内。
即資源建立和資源被轉換為資源管理對象過程中,可能發生異常幹擾。是以建議将上述函數調用改為:
std::shared_ptr<Widget> pw(new Widget)
processWidget(pw,priority());