Effective C 筆記 3 資源管理

2021-09-24 17:07:06 字數 3885 閱讀 1526

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...