class investment
investment* createinvestment(); //返回指標,指向investment繼承體系內的動態分配單元
void f()
把資源放入物件內,便可依賴c++的析構函式自動呼叫機制確保資源被釋放
許多資源被動態分配與堆中,而後被用於單一區塊或函式內,他們應該在控制流離開那個區塊或函式時被釋放
auto_ptr:析構函式自動對其所指物件呼叫delete
注意:別讓多個auto_ptr指向同一物件
void f()
若通過複製建構函式或複製操作符複製它們,會變成null,複製所得的指標將取得資源唯一擁有權
std::auto_ptrpinv1(createinvestment()); //pinv1指向createinvestment返回物
std::auto_ptrpinv2(pinv1); //pinv2指向物件 pinv1設為null
pinv1=pinv2; //pinv1指向物件 pinv2設為null
tr1::shared_ptr:持續追蹤共有多少物件指向某筆資源,並在無人指向它時自動刪除該資源
void f()
//pinv1和pinv2被銷毀,所指物件也被銷毀
資源取得時機便是初始化時機(raii)
class lock
~lock()
private:
mutex *mutexptr;
};
問題:當乙個raii物件被複製時會發生什麼事??
解決:(1)禁止複製。將複製操作宣告為private(條款06)
class lock:private uncopyable;
(2)對底層資源使用「引用計數法」
只要內含乙個tr1::shared_ptr成員變數,raii class可以實現「引用計數」複製行為
tr1::shared_ptr指定「刪除器」,當引用次數為0時便呼叫
class lock
private:
std::tr1::shared_ptrmutexptr; // 使用shared_ptr替換raw point
};
(3)複製底部資源
複製資源管理物件時,進行的是「深度拷貝」
「指向堆記憶體」的指標構成的字串物件被複製,無論指標或是其所指向記憶體都會被製作出乙個複製
(4)轉移底部資源的擁有權
raii物件被複製,永遠只有乙個raii物件指向乙個未加工資源,此時,資源擁有權會從被複製物轉移到目標物
std::tr1::shared_ptrpinv(createinvestment());
// 某個函式處理investment物件:
int daysheld(const investment* pi); // 返回投資天數
將raii物件轉化為所含的原始資源:
(1)顯式轉換
get()成員函式:返回智慧型指標內部原始指標:
int days = daysheld(pinv.get());
tr1::shared_ptr和auto_ptr也過載了指標取值操作符(operator->和operator*),允許隱式轉換至底部原始指標:
class investment ;
investment* createinvestment(); // factory函式
std::tr1::shared_ptrpi1(createinvestment()); // std::tr1::shared_ptr統一管理一筆資源
bool taxable1 = !(pi1->istaxfree()); // 經由operator->訪問資源
...std::auto_ptrpi2(createinvestment()); // std::auto_ptr統一管理一筆資源
bool taxable2 = !((*pi2).istaxfree()); // 經由operator*訪問資源
...
(2)隱式轉換
fonthandle getfont();
void releasefont(fonthandle fh);
class font
~font()
private:
fonthandle f;
};
假設處理的是fonthandle,將font轉換為fonthandle會是一種很繁瑣的要求,font class可為此提供乙個顯式的轉換函式,像get那樣:
class font
...};...
font f(getfont());
changefontsize(f.get(),newfontsize); // font轉化為fonthandle
另一種方法是令font提供隱式轉換函式:
class font
...};...
font f(getfont());
changefontsize(f,newfontsize); // font轉化為fonthandle
顯式轉換比較安全,但隱式轉換對客戶比較方便
使用new,會有兩件事發生:
(1)記憶體被分配出來(通過operator new的函式)
(2)針對此記憶體會有乙個建構函式被呼叫
使用delete,會有兩件事發生:
(1)針對此記憶體會有乙個建構函式被呼叫
(2)記憶體通過operator delete的函式被釋放
使用delete時加上[ ],delete認定指標指向乙個陣列,否則指向單一物件
std::string* stringptr1 = new std::string;
std::string* stringptr2 = new std::string[100];
...delete stringptr1; // 刪除乙個物件
delete stringptr2; // 刪除乙個由物件組成的陣列
int priority();
void processwidget(std::tr1::shared_ptrpw, int priority);
呼叫processwidget():
processwidget(widget, priority()); // error: 不能通過編譯
寫成這樣可以通過編譯:
processwidget(std::tr1::shared_ptr(new widget), priority()); // 可能造成記憶體洩漏
在呼叫processwidget之前,編譯器建立**,做三件事:
(1)呼叫priority
(2)執行new widget
(3)呼叫std::tr1::shared_ptr建構函式
但呼叫次序不定,若先呼叫priority,導致異常,則new widget返回指標遺失
避免這類問題的方法:分離語句
分別寫出(1)建立widget;(2)將它置入乙個智慧型指標內;(3)把智慧型指標傳給processwidget
std::tr1::shared_ptrpw(new widget)
processwidget(pw, priority());
Effective C 3 資源管理
problem void f solution.1 使用auto ptr智慧型指標確保資源的釋放,避免記憶體洩露 void f key points 以物件管理資源 的兩個關鍵想法 1.獲得資源後立刻放進管理物件內 如auto ptr 2.管理物件運用析構函式確保資源被釋放 attention au...
Effective C 總結 3 資源管理
資源管理,一旦用了,就必須將其還給系統。資源包括動態記憶體分配,檔案描述器,互斥鎖,圖形介面的字型,筆刷,資料庫連線,網路sockets。遇到的問題 voidf 在上述 中,在heap上申請記憶體空間,然後經過 然後使用delete釋放申請的記憶體空間。但是,在 的執行過程中,可能會存在return...
effective c 學習筆記3
條款05 了解c 預設編寫並呼叫了那些函式 當你寫下 class empty 這行 後,實際上編譯器為你寫好了如下 class empty default建構函式 empty const empty rhs copy建構函式 empty 析構函式 empty operator const empty...