国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - C/C++ - Effective C++ 高階筆記

Effective C++ 高階筆記

2022-01-12 23:30C語言與C++編程 C/C++

C++并不是一個帶有一組守則的一體語言:他是從四個次語言( C、Object-Oriented C++、Template、STL ) 組成的聯(lián)邦政府,每個次語言都有自己的規(guī)約。記住這四個次于語言你就會發(fā)現(xiàn)C++容易了解得多。

Effective C++ 高階筆記

 Part1一、讓自己習慣C++

條款01:視C++為一個語言聯(lián)邦

C++并不是一個帶有一組守則的一體語言:他是從四個次語言( C、Object-Oriented C++、Template、STL )  組成的聯(lián)邦政府,每個次語言都有自己的規(guī)約。記住這四個次于語言你就會發(fā)現(xiàn)C++容易了解得多。

條款02:盡量以const,enum,inline替換 #define

 #define ASPECT_RATIO 1.653

以上句為例,是通過預處理器處理而不是編譯器處理,有可能ASPECT_RATIO 沒進入記號表內,于是如果出現(xiàn)了編譯錯誤,那么編譯器會提示錯誤信息是 1.653  而不是 ASPECT_RATIO ,你會感到非常困惑。

解決方法是用常量替換宏

const double AspectRatio = 1.653

這樣編譯器就可以看到ASPECT_RATIO ,而且使用常量會使代碼量較小,因為預處理器只會盲目的替換而出現(xiàn)多份 1.653

string對象通常比char* 更好一點

對于class的專屬常量,為了限制作用域在class內,并且防止產生多個實體,最好使用static

  1. 如果你的編譯器支持在類內對const static 整數(shù)類型聲明時獲初值,則使用

  2. 如果不支持,則在類內定義,在對應的實現(xiàn)文件中賦值

如果你需要在編譯器就使用一個class常量值,則應最好改用枚舉類型enum,且枚舉不能用來取地址,不會為它分配額外的存儲空間對于形似函數(shù)的宏,最好改用inline的模板函數(shù)

條款 03:盡可能使用const

const出現(xiàn)在星號左邊目標是指物是常量,出現(xiàn)在星號右邊表示指針本身是常量,如果出現(xiàn)在兩邊,則指針和物都是常量void f1(const Widget* pw)和void f2(Widget const* pw)兩種寫法意義相同,都表示被指物是常量 對于STL迭代器來說,如果你希望迭代器所指的動科不可改動,你需要的是const_iterator 令函數(shù)返回一個常量值,往往可以降低因客戶錯誤而造成的意外(例如把一個值賦值給一個返回值) 將const實施與成員函數(shù)的目的是為了明確該成員函數(shù)可作用于const對象:

  1. 他們使class接口比較容易理解

  2. 他們使得可以操作const對象

const成員函數(shù)和no-const成員函數(shù)可重載,即可以同時出現(xiàn),在傳入不同的參數(shù)時候會調用不同的版本,但是有時我們需要這樣,但是又不想代碼重復,我們可以在no-const成員調用const成員函數(shù)來處理這個代碼重復問題 例如:const_cast<char &>( static_cast<const TextBlock&>(*this)[position]);,經過這樣里面 先安全轉型使得調用的是const版本,外面再去const轉型

條款 04:確定對象被使用前已先被初始化

對于內置類型要進行手工初始化構造函數(shù)最好使用成員初值列表,不要在構造函數(shù)中使用賦值操作來初始化,而且初值列表列出的成員變量次序應該和在class中聲明的次序一樣,因為聲明次序就是C++保證的初始化次序 對于static對象,在跨編譯單元之間的初始化次序是不能確定的,因為C++只保證在本文件內使用之前一定被初始化了

舉例(使用如下方式可以解決這個問題即以loacl static對象替換non-local static對象):

  1. class FileSystem{...};  
  2. FileSystem& tfs(){  
  3.     static FileSystem fs;  
  4.     return fs;  

Part2二、構造/析構/賦值運算

條款05:了解C++默默編寫并調用了哪些函數(shù)

如果你不定義,編譯器會自動幫你實習默認的構造函數(shù),析構函數(shù),拷貝賦值運算符和拷貝構造函數(shù),但是如下幾種情況不會替你生成默認的拷貝賦值運算符

  1. 類中含有**引用**的成員變量

  2. 類中含有**const**的成員變量

  3. 類的**基類**中的拷貝賦值運算符是**私有**成員函數(shù)

條款06:若不想使用編譯器自動生成的函數(shù),就應該明確拒絕

當我們不希望編譯器幫我們生成相應的成員函數(shù)的時候,我們可以將其聲明為private并且不予以實現(xiàn)

條款07:為多態(tài)基類聲明virtual析構函數(shù)

以下情況應該為類聲明一個virtual析構函數(shù):

  1. 用來作為帶有多態(tài)性質的基類的類

  2. 一個類中帶有任何virtual函數(shù)

如果類的設計目的不是作為基類使用,那么就不應該為它聲明virtual析構函數(shù)

條款08:別讓異常逃離析構函數(shù)

析構函數(shù)不要吐出異常,如果實在要拋出異常,那么最好使用std::abort();,放在catch中,把這個行為壓下去 如果某個動作可能會拋出異常,那么最好把它放在普通函數(shù)中,而不是放在析構函數(shù)里面,讓客戶來執(zhí)行這個函數(shù)并去處理

條款09:絕不再構造和析構函數(shù)中調用virtual函數(shù)

在構造和析構的時候,不要試圖調用或在調用的函數(shù)中調用virtual函數(shù),因為會調用父類版本導致出現(xiàn)一些未定義的錯誤

解決辦法之一:

  1. class Transaction{  
  2.     publci:  
  3.      explicit Transaction(const std::string& logInfo);  
  4.      void logTransaction(const std::string& logIngo) const;//把它變成這樣的non-virtual函數(shù)  
  5.      ...  
  6. };  
  7. Transaction::Transaction(const std::string& logInfo){  
  8.     ...  
  9.     logTransaction(logInfo);//這樣調用  
  10.  
  11. class BuyTransaction: public Transaction{  
  12.      BuyTransaction( parameters ):Transaction(createLogString( parameters )){...}//將log信息傳給基類的構造函數(shù)  
  13.     private:  
  14.      static std::string createLogString( parameters );//注意此函數(shù)為static函數(shù)  

條款10:令operator= 返回一個reference to *this

為了實現(xiàn)連鎖賦值如內置類型x= y = z =15由于=采用右結合律,所以等價于x = (y = (z = 15)),因此,為了使我們自定義類也實現(xiàn),所以*重載=,+=,-=,*=使其返回refercence to this

條款11:在operator= 中處理“自我賦值”

在賦值的時候會出現(xiàn)對自我進行賦值的情況,這種情況下我們很容易寫出不安全的代碼

  1. Widget::operator=(const Widget& rhs){  
  2.  delete pb; //把自己釋放了  
  3.  pb = new Bitmap(*rhs.pb);//這就不安全了  
  4.  return *this;  

因此有三種推薦的做法

  1. 先驗證是不是相同的,是不是自我賦值 
  1. Widget::operator=(const Widget& rhs){  
  2. if(this == &rhs) return *this;//驗證是不是相同  
  3.  delete pb;   
  4.  pb = new Bitmap(*rhs.pb);  
  5.  return *this; 
  6.  

 2. 在復制pb所指的東西之前別刪除pb

  1. Widget::operator=(const Widget& rhs){  
  2.  Bitmap* pOrig = pb 
  3.  pb = new Bitmap(*rhs.pb);//讓pb指向*pb的一個副本  
  4.     delete pOrig; //刪除原先的pb  
  5.  return *this; 
  6.  

  3. 使用交換數(shù)據(jù)的函數(shù)

  1. class Widget{  
  2. ...  
  3. void swap(Widget& rhs);//交換*this和rhs的數(shù)據(jù)  
  4. ...  
  5. };  
  6. Widget::operator=(const Widget& rhs){  
  7.  Widget temp(rhs);//創(chuàng)建一個rhs副本  
  8.  swap(temp);//交換*this和上面的副本  
  9.  return *this;  

條款12:復制對象時勿忘其每一個成分

為了確保復制的時候復制對象內的所有成員變量,我們應該在字類的構造和賦值函數(shù)中調用父類的構造和賦值函數(shù)來完成各自的任務 不要嘗試在復制構造函數(shù)和賦值函數(shù)中相互調用,如果想消除重復代碼,請建立一個新的成員函數(shù),并且最好將其設為私有且命名為init

Part3三、資源管理

條款13:以對象管理資源

為了防止資源泄露,我們應該在構造函數(shù)中獲取資源,在析構函數(shù)中釋放資源,這樣可以有效的避免資源泄露 使用智能指針是一個好的辦法,在C++11中auto_ptr已經被棄用,有三個常用的是unique_ptr,share_ptr和weak_ptr

條款14:在資源管理類中心copying行為

我們在管理RAII(構造函數(shù)中獲得,析構函數(shù)中釋放)觀念的類時,應該對不同的情況,根據(jù)不同的目的進行處理

  1. 當我們處理不能同步擁有的資源的時候,可以才用**禁止復制**,如把copying操作聲明為private

  2. 當我們希望共同擁有資源的時候,可以采用**引用計數(shù)法**,例如使用shared_ptr

  3. 當我們需要拷貝的時候,可以采用**深拷貝**

  4. 或者某些時候我們可以采用**轉移**底部資源擁有權的方式

條款15:在資源管理類中提供對原始資源的訪問

有的api函數(shù)往往需要訪問類的原始資源,所以每一個RAII類應該提供一個返回其管理的原始資源的方法 返回原始資源可以使用顯示轉換也可以使用隱式轉換,但是往往顯示轉換更加安全一點,但是隱式轉換更加方便

  1. class Font{  
  2.  ...  
  3.  FontHandle get() const {return f;} //顯示轉換  
  4.  ...  
  5.  operator FontHandle() const {return f;} //隱式轉換函數(shù)  
  6.  ....  
  7.  private:  
  8.   FontHandle f; //管理的原始資源  

條款16:成對使用new和delete時要采用相同形式

不要對數(shù)組形式做typedef,因為這樣會導致delete的時候調用的是delete ptr而不是delete [] ptr,對內置類型會出現(xiàn)未定義或有害的,對類的類型會導致無法調用剩余的析構函數(shù),導致類中管理的資源無法釋放,從而造成內存泄漏 在new 表達式中使用[ ] ,則在相應的delete 表達式中也使用 [ ]

條款17:以獨立語句將newed對象置入智能指針

諸如這樣的語句processWidget (std::tr1::shared_ptr(new Widget),priority())

  1. 在先執(zhí)行new Widget`語句和調用std::tr1::shared_ptr構造函數(shù)之間

  2. 不能確定priority函數(shù)的執(zhí)行順序,可能在最前面,也可能在他們的中間

Part4四、設計與聲明

條款18:讓接口容易被正確使用,不易被誤用

我們接口應該替客戶著想,考慮周全,避免它們犯錯誤。例如在向函數(shù)傳遞日期的時候,把日期參數(shù)做成類的形式,并且用static成員函數(shù)來返回固定的月份,避免用戶參數(shù)寫錯 接口應該和內置接口保持一致,避免讓客戶感覺不舒服,這方面STL做的很好 tr1::shared_ptr支持定制型刪除器,使用它可以防范跨DLL構建和刪除的問題,可以用它來自動解除互斥鎖

條款19:設計class猶如設計type

謹慎的設計一個類,應該遵守以下規(guī)范

  1. 合理的構建class的構造函數(shù)、析構函數(shù)和內存分配函數(shù)以及釋放函數(shù)

  2. 不能把初始化和賦值搞混了

  3. 如果你的類需要被用來以值傳遞,復制構造函數(shù)應該設計一個通過值傳遞的版本

  4. 你應該給你的成員變量加約束條件,保證他們是合法值,所以你的成員函數(shù)必須擔負起錯誤檢查工作

  5. 如果你是派生類,那么你應該遵守基類的一些規(guī)范,如析構函數(shù)是否為virtural

  6. 你是否允許你的class有轉換函數(shù),,是否允許隱式轉換。如果你只允許explicit構造函數(shù)存在,就得寫出專門負責執(zhí)行轉換的函數(shù)

  7. 想清楚你的類應該有哪些函數(shù)和成員

  8. 哪些應該設計為私有

  9. 哪個應該是你的friend,以及將他們嵌套與另一個是否合理

  10. 對效率,異常安全性以及資源運用提供了哪些保證

  11. 如果你定義的不是一個新type,而是定義整個type家族,那么你應該定義一個類模板

  12. 如果只是定義新的字類以便為已有的類添加機制,說不定單純定義一個或多個non-member函數(shù)或模板更好

條款20:寧以pass-by-reference-to-const替換pass-by-value

盡量以pass-by-reference-to-const替換pass-by-value,因為前者通常比較高效,比如在含有類的傳遞時,避免了多次構造函數(shù)和多次析構函數(shù)的調用,大大的提高了效率 但是對于某些,比如內置類型,迭代器,函數(shù)調用等最好以值傳遞的形式

條款21:必須返回對象時,別妄想返回其reference

絕對不能返回指針或者一個引用指向一個臨時變量,因為它存在棧中,一旦函數(shù)調用結束返回那么你得到的將是一個壞指針,也不能使用static變量來解決,你可以通過返回值 來解決

條款22:將成員變量聲明為private

  1. 為了保證一致性

  2. 可以細微的劃分訪問和控制以及約束

  3. 內部更改后不影響使用

protected并不比public更具封裝性

條款23:寧以non-member、non-friend、替換member函數(shù)

我們可以用non-member、non-friend函數(shù)來替換某些成員函數(shù),可以增加類的封裝性,包裹彈性和擴充性

條款24:若所有參數(shù)皆需要類型轉換,請為此采用non-member函數(shù)

如果你需要為某個函數(shù)的所有參數(shù)(包括被this指針所指的那個隱喻參數(shù))進行類型轉換,那么這個函數(shù)必須是個non-member

條款25:考慮寫出一個不拋出異常的swap函數(shù)

在你沒有定義swap函數(shù)的情況下,編譯器會為你調用通用的swap函數(shù),但是有的時候那并不是高效的,因為默認情況它在置換如指針的時候把整個內存都置換 我們采取一種解決辦法 1. 在類中提供一個 public swap成員函數(shù),并且這個函數(shù)不能拋出異常2. 在類的命名空間中提供一個non-member swap函數(shù),并令它調用類中的swap函數(shù) 3. 如果你正在編寫一個類而不是模板類,為你的class特化std::swap函數(shù),并令它調用你的swap函數(shù) 4. 請在類中聲明 using std::swap,讓其暴露,使得編譯器自行選擇更合適的版本

Part5五、實現(xiàn)

條款26:盡可能延后變量定義式的出現(xiàn)時間

定義一個變量,那么你就得承受這個變量的構造和析構的成本時間,所以在定義一個變量的時候我們應該盡可能的延后定義時間,在使用前定義,這樣避免我們定義了卻沒有使用它,造成浪費

條款27:盡量少做轉型動作

舊式轉型是C風格的轉型,C++中提供四種新式轉型:

  1.  const_cast 通常被用來將對象的常量性轉除。它也是唯一有此能力的轉型操作符
  2.  dynamic_cast 主要用來執(zhí)行“安全向下轉型” ,也就是用來決定對某對象是否歸屬繼承體系中的某個類型。它是唯一無法由舊式語法執(zhí)行的動作,也是唯一可能耗費重大運行成本的轉型動作
  3.  reinterpret_cast 意圖執(zhí)行低級轉型,實際動作(及結果)可能取決于編譯器,這也就表示它不可移植。例如將一個pointer to int轉型為一個int。這一類轉型在低級代碼以外很少見。
  4.  static_cast 用來強迫隱式轉換,例如將non-const對象轉換為const對象,或將int轉為double等等,它也可以用來執(zhí)行上述多種轉換的反向轉換,例如將void* 指針轉為 type 指針,將pointer-to-base 轉為 pointer-ro-derived 。但它無法將 const 轉為 non-const ——這個只有const_cast才能辦到

舊式轉型使用的時機是,當要調用一個explicit構造函數(shù)對一個對象傳遞給一個函數(shù)時,其他盡量用新式轉型

請記住以下:

  1. 如果可以的話,避免dynamic_cast轉型,如果實在需要,則可以試著用別的無轉型方案代替

  2. 如果轉型是必要的,那么應該把他隱藏于某個函數(shù)背后,客戶隨后可以調用該函數(shù),而不是需要將轉型放進自己的代碼里

  3. 寧可要新型轉型,也不要使用舊式轉型

條款28:避免返回handles指向對象內部成分

避免返回handle(包括引用,指針和迭代器)指向對象內部。這樣可以增加封裝性,也能把出現(xiàn)空懸指針的可能性降低

條款29:為“異常安全”而努力是值得的

異常安全函數(shù)提供以下三個保證之一:基本承諾:如果異常被拋出,程序內的任何事物仍然保持在有效狀態(tài)下。沒有任何對象或數(shù)據(jù)會因此而敗壞,所有對象都處于一種內部前后一致的狀態(tài)。然而程序的現(xiàn)實狀態(tài)恐怕不可預料強烈保證:如果異常被拋出,程序狀態(tài)不改變。調用這樣的函數(shù)需要有這樣的認知:如果函數(shù)成功,就是完全成功,如果函數(shù)失敗,程序會恢復到“調用之前”的狀態(tài)不拋擲保證:承諾絕不拋出異常,因為它們總是能夠完成他們原先承諾的功能。作用于內置類型身上所有操作都提供nothrow保證,這是異常安全碼中一個必不可少的關鍵基礎材料

這三種保證是遞增的關系,但是如果我們實在做不到,那么可以提供第一個基本承諾,我們在寫的時候應該想如何讓它具備異常安全性

  1. 首先以對象管理資源可以阻止資源泄漏

  2. 在你能實現(xiàn)的情況下,盡量滿足以上的最高等級

條款30:透徹了解inlining 的里里外外

inline 聲明的兩種方式:

  1. 隱喻的inline申請,即把定義寫在class內部

  2. 明確聲明,即在定義式前加上關鍵字inline

將大多數(shù)inlining限制在小型、被頻繁調用的函數(shù)身上。這可使日后調試和二進制升級更容易,也可使得潛在的代碼膨脹問題最小化。不要只因為function templates出現(xiàn)在頭文件,就將他們聲明為inline

條款31:將文件間的編譯依存關系降至最低

支持“編譯依存性最小化”的思想是:相依于聲明式,不要相依于定義式

  1. 頭文件和實現(xiàn)相分離,頭文件完全且僅有聲明式

  2. 使用創(chuàng)建接口類

Part6六、繼承與面向對象設計

條款32:確定你的public繼承塑模出is-a關系

public繼承意味著is-a的關系,即子類是父類的一種特殊化,適合基類的一定適合子類,每個派生類對象含有著父類對象的特點

條款33:避免遮掩繼承而來的名稱

在父類中的名稱會被字類的名稱覆蓋,尤其是在public繼承下,沒有人希望這樣的發(fā)生 為了避免被遮掩,可以使用using聲明式或轉交函數(shù),交給子類

條款34:區(qū)分接口繼承和接口實現(xiàn)

聲明純虛函數(shù)的目的就是為了讓派生類只繼承函數(shù)接口 聲明虛函數(shù)的目的是讓派生類繼承該函數(shù)的接口和缺省實現(xiàn) 聲明普通函數(shù)的目的就是讓派生類強制接受自己的代碼,不希望重新定義

條款35:考慮virtual函數(shù)以外的其他選擇

條款36:絕不重新定義繼承而來的non-virtual函數(shù)

任何情況下都不應該重新定義一個繼承而來的non-virtual函數(shù)

條款37:絕不重新定義繼承而來的缺省參數(shù)值

絕對不要重新定義一個繼承而來的缺省參數(shù)值,因為缺省參數(shù)值都是靜態(tài)綁定的,而virtual函數(shù)——你唯一應該覆寫的東西是動態(tài)綁定

條款38:通過復合塑模has-a或“根據(jù)某物實現(xiàn)出”

區(qū)分public繼承和復合 在應用領域,復合意味著一個中含有另一個,即has-a關系;在實現(xiàn)領域意味著根據(jù)某物實現(xiàn)出

條款39:明智而審慎地使用private繼承

當需要復合時,盡可能的使用復合,必要時才使用private: 當protected成員或virtual函數(shù)牽扯進來的時候 當空間方面的利害關系,需要尺寸最小化

條款40:明智而審慎地使用多重繼承

多重繼承時候,如果其父類又繼承同一個父類,所以解決的方式就是使用virtual繼承,即其父類同時以virtual繼承那個父類,但是相應的也會付出一些代價,例如時間更慢,需要重新定義父類的初始化等,因此設計時最好不要讓這個父類有任何數(shù)據(jù)成員當單一繼承和多重繼承都可以,那么最好選擇單一繼承,多重繼承也有正當?shù)挠猛荆梢詫崿F(xiàn)同時public繼承和private繼承的組合

Part7七、模板與泛型編程

條款41:了解隱式接口和編譯期多態(tài)

顯式接口:由函數(shù)的簽名式(也就是函數(shù)名稱、參數(shù)類型、返回類型)構成 隱式接口:不基于函數(shù)簽名式,而是由有效表達式組成 面向對象和泛型編程都支持接口和多態(tài),只不過一個以顯式為主,一個以隱式為主 兩種多態(tài)一個在運行期一個在編譯期

條款42:了解typename的雙重意義

聲明模板參數(shù)的時候,class和typename是可以互換的,沒什么不一樣 但是標識嵌套從屬類型名稱的時候必須用typename 不得在基類列(繼承的時候)或成員初值列(初始化列表)內以它作為基類修飾符

  1. templete<typename T>  
  2. class Derived:public Base<T>::Nested{ //基類列表中不可以加“typename”  
  3. public:  
  4.     explicit Derived(int x): Base<T>::Nested(x){//mem.init.list中不允許“typename”  
  5.         typename Base<T>::Nested temp; //這個是嵌套從屬類型名稱  
  6.         ... //作為一個基類修飾符需要加上typename  
  7.     }  
  8. }    

條款43:學習處理模板化基類內的名稱

模板化基類指的是當派生類的基類是一個模板

  1. 在基類函數(shù)調用之前加上  this->

  2. 使用 using 聲明式  ,告訴編譯器,請它假設這個函數(shù)存在

  3. 指出這個函數(shù)在基類中,使用基類::函數(shù)的形式寫出來(不推薦這個,因為如果是virtual函數(shù),則 會影響動態(tài)綁定)

 但是當有模板全特化的時候,確實使用的沒有這個函數(shù),那么依然會報錯

條款44:將與參數(shù)無關的代碼抽離出來

模板生成多個類和多個函數(shù),所以任何模板代碼都不該和某個造成膨脹的模板參數(shù)產生相依關系 因非類型模板參數(shù)造成的代碼膨脹,往往可以消除,做法是以函數(shù)參數(shù)或類成員變量替換模板參數(shù) 因類型模板參數(shù)造成的代碼膨脹,往往可以降低,做法是讓帶有完全相同的二進制表述 的具體類型共享實現(xiàn)碼

條款45:運用成員函數(shù)模板接受所有兼容類型

使用成員函數(shù)模板可以生成接收所有兼容類型的函數(shù) 如果你聲明成員函數(shù)模板用來泛化拷貝構造函數(shù)和賦值操作,那么你還需要聲明正常的拷貝構造函數(shù)和賦值操作

條款46:需要類型轉換時請為模板定義非成員函數(shù)

當我們編寫一個模板類,它提供的和這個模板祥光的函數(shù)支持所有參數(shù)的隱式類型轉換,請將哪些函數(shù)定義為模板類的內部的friend函數(shù)

Part8八、定制new和delete

條款49:了解new—handler的行為

當new分配失敗的時候,它會先調用一個客戶指定的錯誤處理函數(shù)(set_new_handler),一個所謂的new—handler 它是一個typedef定義出一個指針指向函數(shù),該函數(shù)沒有參數(shù)也不返回任何東西 set_new_handler的參數(shù)是個指針指向operator new 無法分配足夠內存時該被調用的函數(shù)。其返回值也是個指針,指向set_new_handler 被調用前正在執(zhí)行(馬上就要被替換)的那個new—handler函數(shù) 一個良好設計的new—handler函數(shù)必須做以下事情:

  1. 讓更多內存可被使用。此策略的一個做法是,程序一開始就分配一大塊內存,而后當其第一次被調用,將它釋還給程序使用

  2. 安裝另一個new—handler。可以設置讓其調用另一個new—handler來替換自己,用來做不同的事情,其做法是調用set_new_handler

  3. 卸載new—handler,也就是將null指針傳給set_new_handler,這樣new在分配不成功時拋出異常

  4. 拋出bad_alloc的異常。

  5. 不返回,調用abort或exit

  6. C++并部支持類的專屬new—handler,但其實也不需要。你可以令每個類提供自己的set_new_handler和operator new即可

     set_new_handler允許客戶指定一個函數(shù),在內存分配無法獲得滿足時調用。

     Nothrow new是一個頗為局限的工具,因為它只適用于內存分配:后繼的構造函數(shù)調用還是可能拋出異常

條款50:了解new和delete的合理替換時機

替換operator new或operator delete的三個常見理由:用來檢測運用上的錯誤 為了收集使用上的統(tǒng)計數(shù)據(jù) 為了增加分配和歸還的速度 為了降低缺省內存管理器帶來的空間額外開銷,也就是實現(xiàn)內存池,可以節(jié)省空間為了彌補缺省分配器中的非最佳齊位 為了將相關對象成簇集中 為了獲得非傳統(tǒng)行為

了解何時可在“全局性的”或“class專屬的”基礎上合理替換缺省的new和delete

條款51:編寫new和delete時需固守常規(guī)

operator new應該內含有一個無窮的循環(huán),并在其中嘗試分配內存,如果它無法滿足內存需求,就該調用new-handler。它也應該有能力處理0 bytes申請,即將其按照1 byte分配。Class 專屬版本應該處理“比正確大小更大的(錯誤)申請”,因為當有字類繼承的時候,會出現(xiàn)傳入的大小和父類大小不同,所以要進行判斷形如if(size != sizeof(父類))operator delete應該在收到NULL指針的時候什么也不做,必要時交給全局的operator new來處理。

條款52:寫了placement new也要寫placement delete

當你寫一個placement operator new ,請確定也寫了對應的placement operator delete版本。如果沒有這樣做,可能回發(fā)生隱微而時斷時續(xù)的內存泄露當你聲明placement new 和placement delete,請確定不要無意識(非故意)地遮掩正常的全局版本,你如果想提供自定義形式,請內含所有正常形式的new和delete或利用繼承機制及using聲明式

Part9九、雜項討論

條款53:不要輕忽編譯器的警告

不同的編譯器有不同的警告標準,要嚴肅對待編譯器發(fā)出的警告信息。努力在你的編譯器的最高警告級別下爭取“無任何警告”的榮譽 不要過度依賴編譯器的報警能力,因為不同的編譯器對待事情的態(tài)度并不相同。一旦移植到另一個編譯器上,你原本依賴的警告信息有可能消失

條款54:讓自己熟悉包括TR1在內的標準程序庫

C++標準程序庫的主要機能由STL、iostream、locales組成。并包含C99標準程序庫。TR1添加了智能指針(例如 tr1::shared_ptr)、一般化函數(shù)指針(tr1::function)、hash-based容器、正則表達式以及另外10個組件的支持 TR1自身知識一份規(guī)范。為了獲得TR1提供的好處,你需要一份實物。一個好的實物來源是Boost。

條款55:讓自己熟悉Boost

Boost是一個社群,也是一個網站。致力于免費、源碼開放、同僚復審的C++程序庫開發(fā)。Boost在C++標準化過程中扮演具有影響力的角色 Boost提供許多TR1組件實現(xiàn)品,以及其他許多程序庫

原文地址:https://mp.weixin.qq.com/s/JUZtEgarDq15ToVIRHsjaw

延伸 · 閱讀

精彩推薦
  • C/C++詳解c語言中的 strcpy和strncpy字符串函數(shù)使用

    詳解c語言中的 strcpy和strncpy字符串函數(shù)使用

    strcpy 和strcnpy函數(shù)是字符串復制函數(shù)。接下來通過本文給大家介紹c語言中的strcpy和strncpy字符串函數(shù)使用,感興趣的朋友跟隨小編要求看看吧...

    spring-go5642021-07-02
  • C/C++C/C++經典實例之模擬計算器示例代碼

    C/C++經典實例之模擬計算器示例代碼

    最近在看到的一個需求,本以為比較簡單,但花了不少時間,所以下面這篇文章主要給大家介紹了關于C/C++經典實例之模擬計算器的相關資料,文中通過示...

    jia150610152021-06-07
  • C/C++C語言中炫酷的文件操作實例詳解

    C語言中炫酷的文件操作實例詳解

    內存中的數(shù)據(jù)都是暫時的,當程序結束時,它們都將丟失,為了永久性的保存大量的數(shù)據(jù),C語言提供了對文件的操作,這篇文章主要給大家介紹了關于C語言中文件...

    針眼_6702022-01-24
  • C/C++深入理解goto語句的替代實現(xiàn)方式分析

    深入理解goto語句的替代實現(xiàn)方式分析

    本篇文章是對goto語句的替代實現(xiàn)方式進行了詳細的分析介紹,需要的朋友參考下...

    C語言教程網7342020-12-03
  • C/C++學習C++編程的必備軟件

    學習C++編程的必備軟件

    本文給大家分享的是作者在學習使用C++進行編程的時候所用到的一些常用的軟件,這里推薦給大家...

    謝恩銘10102021-05-08
  • C/C++c++ 單線程實現(xiàn)同時監(jiān)聽多個端口

    c++ 單線程實現(xiàn)同時監(jiān)聽多個端口

    這篇文章主要介紹了c++ 單線程實現(xiàn)同時監(jiān)聽多個端口的方法,幫助大家更好的理解和學習使用c++,感興趣的朋友可以了解下...

    源之緣11542021-10-27
  • C/C++C++之重載 重定義與重寫用法詳解

    C++之重載 重定義與重寫用法詳解

    這篇文章主要介紹了C++之重載 重定義與重寫用法詳解,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下...

    青山的青6062022-01-04
  • C/C++C語言實現(xiàn)電腦關機程序

    C語言實現(xiàn)電腦關機程序

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)電腦關機程序,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    xiaocaidayong8482021-08-20
主站蜘蛛池模板: 久久久久一区 | 国产毛片久久 | 亚洲 欧美 日韩在线 | 久草免费在线 | 在线 亚洲 欧美 | 国产精品成人3p一区二区三区 | 黄色影视在线免费观看 | 激情网站免费观看 | 性激烈欧美三级在线播放狩猎 | 亚洲日本韩国在线观看 | 蜜桃免费视频 | 亚洲一区在线视频 | 九色91| 青青av| 中文字幕在线观看一区二区三区 | 久久久精品黄色 | 国产一级纯肉体一级毛片 | 亚洲激情网站 | 亚洲综合色自拍一区 | 日韩在线视频在线观看 | 日韩一区二区三区精品 | www中文字幕 | 久久亚洲精品国产精品紫薇 | 久久久久久久久久久九 | 在线国产日韩 | 成人午夜精品久久久久久久网站 | 国产毛片欧美毛片久久久 | 久久久久久久久99精品 | 午夜视频在线网站 | 日韩一区在线视频 | 色综合一区二区三区 | 91精品国产乱码久久久久久 | 国产a自拍 | 一级片在线播放 | 成人爽a毛片一区二区免费 久久久久亚洲精品 | 黄色在线免费 | 亚洲精品欧美一区二区三区 | 国产一区二区三区午夜 | 日日操综合 | 在线视频91| 日本午夜视频 |