Exceptional C++ 讀書筆記

?//內(nèi)存管理的一部分來自于http://blog.csdn.net/kingofark/category/9109.aspx
?Item 1 Iterator:
???
?(1): 注意當前迭代器是否有效,如果無效則解引用產(chǎn)生程序錯誤;
?(2):注意當前迭代器生命期,某些容器經(jīng)過某些操作后將重新分配內(nèi)部存儲空間,則當前迭代器無效;
?(3) : 有效范圍, 類似find(first, last, value)時, 迭代器first 必須在last之前,必須保證指向同一個容器;
?????? (4): 有效的內(nèi)部操作;

?Item 2, 3: Case-Insensitive String
?????
?(1) 1 關于std::string: std::string實際是
??template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> >
??class basic_string;
??typedef basic_string<char> string;
??要實現(xiàn)case-insensitive string需要改變string的compare方式,因為char_traits<char>類提供compare等方式,所以
??就需要對char_traits<char>作相應的變動;
??char_traits::eq()和lt()提供相等和小于的對比方式,compare()和find()提供對比和搜索字符串序列的功能;更改這四個成員函數(shù)??就可以實現(xiàn)case-insensitive string;
?(2)關于實際應用中,最好選用一個單一的函數(shù)去接受兩個相應的std::string對象,而非用更改traits的方法來實現(xiàn)一個ci_string;
?例如 bool CaseInsensitiveString(std::string &a, std::string &b)
?(3)類似ci_char_traits : public char_traits<char>, 用于變換traits或者iterator功能等情形,而非當作傳統(tǒng)的OO方式來使用時,可以當作合理的派生,不必考慮virtual destructor等;
?
?Item 4, 5 Max Reusable Generic Containers
?(1) template constructor永遠不會是一個copy constructor, 因為永遠存在一個最適合的copy constructor, 因此overload resolution決不會將template constructor 當作copy constructor
?
?(2) 善于使用模板成員函數(shù)

?Item 6, 7 Temporary Objects
?
?(1) a: 用傳遞const T& 代替?zhèn)髦?
???????? b: 用預先創(chuàng)建的對象代替不需要的重復創(chuàng)建的對象,類似(container.end()每次被調(diào)用將返回一個臨時的對象,這是不必要的);
???? c: 用++T 代替 T++ (因為T++ 一般先制造一個臨時對象,然后更新本身,最后返回臨時對象);
???????? d: 用++T來實現(xiàn)T++;
???? e: 避免做無用的隱式轉換;
?
?(2) 注意對象生命期,絕不準讓函數(shù)返回一個函數(shù)內(nèi)部的auto變量的指針或者引用;
?(3) 多用標準庫的代碼;

?Item 8 -- 17 Writing Exception-Safe Code
?(1)當一個函數(shù)不能處理內(nèi)部的異常時,應當將它拋給函數(shù)調(diào)用者去處理;
?(2) 當異常出現(xiàn)時,請讓資源正確的被釋放,數(shù)據(jù)處于一個穩(wěn)定的狀態(tài);
?(3)絕不能讓從destructor或者被重載的delete中拋出,寫析構函數(shù)和資源分配函數(shù)時應當寫上throw();?
?(4)先將所有可能拋出異常的操作和安全的的操作分離出來,當可能拋出異常的操作執(zhí)行成功時,再用no throw操作改變對象狀態(tài);
?(5)讓每一個代碼片段(類,模塊,函數(shù))負責單一的任務,類似STL stack中的pop和top是分離的
?
?(6): exception-safe基本準則:
??A: 基本安全: 當異常拋出時不產(chǎn)生資源泄漏;
??B: 健壯的安全性:如果某個操作因為異常的拋出而終止,則對象當前狀態(tài)不應改變;
??C: 不拋出異常: 約定這個函數(shù)決不拋出異常;
?
?(7): 將資源管理單獨的封裝成一個類類似書上的例子 StackImpl封裝了內(nèi)存管理功能
?(8): 多用聚合,少用繼承(包括這種聚合 pivate繼承 -- 因為這將導致在constructor中無法控制base class
?(9): 用資源申請既初始化來隔離類的實現(xiàn)和資源的管理與所有權
?
?(10): 什么時候應當用private繼承代替containment?
??a: 需要存取某個類的protected成員
??b: 需要覆寫虛函數(shù)
??c: base 對象需要在其他類對象建構之前建構
?(11): 析構函數(shù)中決不允許拋出異常:
??a: 對象本身所申請的的資源不能完全釋放;
??b:考慮 T t[20];的情況;析構某個T時拋出異常會產(chǎn)生未定義情況
??
Item 18, 19 Code Complexity
?(1): 提供強異常安全需要損失一定程度的性能;
?(2): 如果一個函數(shù)存在幾個不相關的副作用,那么它不可能實現(xiàn)異常安全, 否則應當把這幾個函數(shù)分割為不同的函數(shù)
?(3): 不是所有的函數(shù)都需要強異常安全;

?Item 20 Class Mechanics
?(1):?設計時首先考慮標準庫是否存在相關的類
?(2): ?用explicit constructor代替隱式轉換
?(3): 如果提供一個常規(guī)的operator op(類似+),那么應該同樣提供一個operator op=(+=),
??operator op(類似的 + - * /)不應該改變對象值, 它應當返回一個 + 操作后的臨時對象;
?(4): 多用a op= b 代替 a = a op b; 一般 const T operator op(T, T)產(chǎn)生一個臨時變量;
?
?(5) ?一元運算符是成員函數(shù)
?????? =,(),[]和->必須是成員函數(shù)
?????? +=,-=,/=,*=(等等)是成員函數(shù)
?????? 所有其它的二元運算符是非成員函數(shù)
?(6) ++T 應當返回一個引用, T++應當返回一個const T,以防止 T++++這種情況發(fā)生;T++應當由++T來實現(xiàn);
?(7) 避免使用前導下劃線來命名,前導下劃線是留給編譯器使用的
?
?Item 21 override 虛函數(shù)?
?(1): 除非確定某個類不被派生,否則都應當提供一個虛函數(shù);
?(2): 關于 overload, override和 hide
??a: overload意思是提供一個相同名稱但是不同參數(shù)的函數(shù), 編譯時由編譯器決定哪個是最匹配的函數(shù)
??b: override意思是在派生類提供一個相同名稱且相同參數(shù)不同實現(xiàn)的虛函數(shù),動態(tài)調(diào)用時將從派生類指針調(diào)用這個函數(shù)
??c: hide 某個函數(shù)的意思是有一個函數(shù)在某個范圍內(nèi)(派生類,嵌套類,名稱空間等),隱藏同名函數(shù)
??
?(3) 當派生類提供一個和基類的某個成員函數(shù)同名的函數(shù)時,如果你不想隱藏基類的同名函數(shù),請在派生類聲明基類的同名函數(shù),
??例如: using Base::f;
?(4) 永遠不要在派生類override virtual function中改變默認參數(shù);
?
?Item 22, 23 Class Relationships
?(1): 什么時候不應該選用public 繼承
????? a: 如果某個類為提供虛函數(shù),這個類本身不打算實施多態(tài);
????? b: 如果某個類未提供protected 成員
????? c: 類型為不是IS-A, WORKS-LIKE-A or USABLE-AS-A;
????? d: 派生類只用了基類的public 成員;
?(2): 只有當需要存取某個類protected 成員或者override 虛函數(shù)的時候才應該選用private繼承;不是IS-A, WORKS-LIKE-A or
????? USABLE-AS-A的時候決不應當用public 繼承;
?
?(3): 避免提供public virtual function, 使用template method 設計模式代替;從算法中提取出那些每次都要進行的步驟,將其抽象出??來,只把一些因地制宜的細節(jié)通過virtual function 留給派生類來實現(xiàn)。
?(4): 應用compiler-firewall 方法隱藏實現(xiàn)細節(jié),使用一個不透明的指針(指向一個聲明但未定義的類
??(struct xxxImpl; xxxImpl *pimpl_)來存private 成員,包括狀態(tài)變量和成員函數(shù));
??例如: clas Map { private: struct MapImpl; MapImpl *pimpl_; };
?
?
?Item 24 Uses and Abuses of Inheritance
?(1): 多用聚合,(containment, composition, layering HAS-A, delegation),當關系模型為 IS-IMPLEMENTED-IN-TERMS-OF時,請多考慮聚合,最好不用繼承;
?(2): 非public 繼承的條件:
??a: 當需要override virtual function時候;
??b: 需要存取基類protected成員時候
??c: 需要保證初始化順序的時候(基類必須建構在派生類之前,析構在派生類之后等情況);
??d: 需要某種多態(tài)的訪問控制時;
?(3): 用public繼承時應當避免的問題:
??a: 如果非public繼承可以做,那么決不要用public繼承;絕不能用public繼承表述一個依據(jù)什么實現(xiàn)的關系模型;
??b: 絕不能用public繼承表述一個 IS-ALMOST-A關系模型(類似正方形是一個矩形等關系模型);
?(4): 應當總是先確定 public繼承關系模型為 IS-A或者WORKS-LIKE-A

?Item 25 Object-Oriented Programming
?略;
?Item 26-28 Minimizing Compile-Time Dependencies
?(1): 決不#include無用的頭文件;
?(2): 當前向聲明某個stream時候用<iosfwd>足夠了;
?(3): 如果composition足夠的話,決不能用繼承;
?
?Item 29 Compilation Firewalls
?(1): 放置所有的非virtual函數(shù) private member 到Pimpl類中去; 客戶程序員無論如何也不應當看到這些private成員;
????? Pimpl類中某些函數(shù)可能需要類中某些成員的支持,所有需要一個back pointer指向類本身,back pointer通常命名為self_
?
?Item 30 The "Fast Pimpl" Idiom
?(1):絕不能放置對象到一個buffer里面,例如
??char buffer[100];
??new (&buffer[0]) T;
??a: 不能保證對齊規(guī)則;
??b: 脆弱
??c: 難于維護;
??
?
?Item 31 - 34 Name Lookup and Interface Principle
?(1): 對于一個class X,任何提及并且含有X(例如來自同一頭文件或者名稱空間)的函數(shù)(括成員函數(shù),static函數(shù)和自由函數(shù)),邏輯上都屬于class X的一部分,因為它們是X接口的一部分
??任何class X的成員函數(shù)都一定提及X;
??任何class X的成員函數(shù)都一定含有X(隱式的this);

??例如:
???class X{...};
???ostream& operator<<(ostream&, const X&)//肯定提及X;
???如果operator<<含有X ,例如在同一個頭文件或者名稱空間,那么它邏輯上屬于X的一部分,因為他建構了X的一部分接口;
???否則反之;
??
?(2): 關于 supplied with;
??struct _iobuf{...};
??typedef struct _iobuf FILE;
??FILE*?fopen(const char *filename, const char* mode);
??int fclose(FILE* stream);
??int fseek(FILE* stream, long offset, int origin);
??......
??這些函數(shù)都是非成員,但是它們確實是 FILE接口的一部分;(part of the interface of FILE);
??class File
??{
??public:
???int fseek(long offset, int origin);
???......
??};
??int fseek(FILE* stream, long offset, int origin);
??例如上例:?int fseek(FILE* stream, long offset, int origin);
??提及并且同F(xiàn)ile都來自于頭一個頭文件或者名稱空間,此函數(shù)一樣屬于File接口的一部分;
?
?(3):如果在某個作用域內(nèi)調(diào)用了一個接受另一個作用域內(nèi)類型參數(shù)的函數(shù),那么編譯器不止在當前作擁域內(nèi)查找該函數(shù),同時也會到接受的的??類型所在的作用域去查找該函數(shù),而且不用特別聲明;類似
??void f()
??{
???std:string hello = "hello world";
???std::cout? <<? hello;?? //正確調(diào)用std::operator<<;
??}
?? 如果沒有Koenig lookup,則編譯器無法查找到operator<<是哪一個我們想要的;(這個函數(shù)封裝在std::string內(nèi),是string接口 的??一部分);如果希望正確調(diào)用的operator<<,我們需要 std::operator<<(std::cout, hello);
??
??所以,如果在同一個名稱空間內(nèi)定義了一個類和一個提及這個類的函數(shù), 那么編譯器將強制關聯(lián)這個類和這個自由函數(shù);
?(4): namespace A { class X {};? void f(X x) {} }
??namespace B { void f(A::X x) {} void g(A:: xx) { f(xx); } }
??這將導致B::g出現(xiàn)二義性而無法編譯;原因在于g涉及A::X,所以編譯時編譯器同樣將名稱空間A內(nèi)的函數(shù)也考慮進來,此時出現(xiàn)兩個參??數(shù)為A::X的函數(shù)f
??類的成員函數(shù)將被優(yōu)先考慮,例如
??namespace A { class X {};? void f(X x) {} }
??class B
??{
???void f(A::X x) {}
???void g(A:: xx) { f(xx); } //此時不會出現(xiàn)二義性問題;
??};
??如果編譯器發(fā)現(xiàn)一個類成員函數(shù)為f(A::X),則不再使用Koenig lookup去搜索自由函數(shù);
??
?(5):結論為名稱空間不像想象的那樣完全隔離函數(shù)聲明,它只能屬于部分獨立;
?
?
?(6): 根據(jù)Interface Principle,如果一個函數(shù)提及了兩個類,class X和class Y, 并且此函數(shù)同X包含在同一個名稱空間或者頭文件之中,那么,首先,此函數(shù)邏輯上是X的界面接口的一部分;由于此函數(shù)依賴Y,因此,X同樣依賴于Y;
?(7): 如果A,B是類,f(A,B)是自由函數(shù), 那么
??a: 如果A和f在同一頭文件或名稱空間內(nèi),那么f邏輯上是A的一部分,所以,A也依賴于B;
??b: 如果A,B和f在同一頭文件或名稱空間內(nèi),那么f邏輯上是A的一部分也是B的一部分,故此,A,B互相依賴;
?
??如果 ,A,B是類,A::g(B)是一個A的成員函數(shù),那么:
??a: 因為A::g(B),所以,A,依賴于B;
??b:如果A,B被聲明在一起(同一個頭文件或名稱空間),那么A,B互相依賴,A::g(B)邏輯上同樣屬于B的一部分;
??實際上,上述情況的實際含義是,類型A,B通常將被放在一起使用,,如果修改了一個,那么將影響另一個;
?(8):關于名稱隱藏:
??struct B
??{
???int f(int);
???int f(double);
???int g(int);
??};
??struct D : public B
??{
??private:
???int g(std::string, bool);
??};
??D d;
??int i;
??d.f(i) ?//調(diào)用B::f(int);
??d.g(i);?//錯誤,提示應當提供兩個參數(shù);
??
??? 實際上,編譯器查找匹配函數(shù)名稱時候,先查找當前范圍內(nèi)的名稱匹配函數(shù),例如這里是D,然后列出一個編譯器所能找到的函??數(shù)名稱?相同的函數(shù)的列表,但 是并不考慮存取權限和所攜帶參數(shù)是否正確,如果它一個名稱匹配的函數(shù)都沒找到的話,那么將向外一層??繼續(xù)查找,如果編譯器找到一個或者多個候選的函數(shù), 編譯器將停止查找,然后提交函數(shù)的重載決議;
??兩種解決方法是
??a: d.B::g(i);//編譯器自然會考慮B的范圍;
??b:
???struct D : public B
???{
???using B::g;
???private:
????int g(std::string, bool);
???};
??
??
??
?(9): 使用名稱空間,如果寫一個類在名稱空間N中,那么請將所有的協(xié)助函數(shù)和操作符都都寫在N中;
Item 35, 36 Memory Management
?
?(1):
??[常量數(shù)據(jù)(const data)區(qū):]
??常量數(shù)據(jù)區(qū)存儲字符串等在編譯期間就能確定的值。類對象不能存在于這個區(qū)域中。在程 序的整個生存周期內(nèi),區(qū)域中的數(shù)據(jù)都是可??用的。區(qū)域內(nèi)所有的數(shù)據(jù)都是只讀的,任何企圖修改本區(qū)域數(shù)據(jù)的行為都會造成無法預料的后果。之所以會如此,是 因為在實際的實現(xiàn)??當中,即使是最底層的內(nèi)部存儲格式也受制于所實現(xiàn)的特定的優(yōu)化方案。例如,一種編譯器完全可以把字符串存放在幾個重疊的對象里??面 ——只要實現(xiàn)者愿意的話。?
??[棧(stack)區(qū):]
??棧區(qū)存儲自動變量(automatic variables)。一般來說,棧區(qū)的分配操作要比動態(tài)存儲區(qū)(比如堆(heap)或者自由存儲區(qū)(free ??store))快得多,這是因為棧區(qū)的分配只涉及到一個指針的遞增,而動態(tài)存儲區(qū)的分配涉及到較為復雜的管理機制。棧區(qū)中,內(nèi)存一??旦被分配,對象 就立即被構造好了;對象一旦被銷毀,分配的內(nèi)存也立即被收回(譯注:這里作者用了“去配(deallocate)”一詞,??鄙人一律翻譯為“回收”)。 因此,在棧區(qū)中,程序員沒有辦法直接操縱那些已經(jīng)被分配但還沒有被初始化的棧空間(當然,那些通過??使用顯式(explicit)析構函數(shù) (destructor)和new運算符而故意這么做的情況不算在內(nèi))。
??[自由存儲區(qū)(free store):]
? ??自由存儲區(qū)(free store)是C++兩個動態(tài)內(nèi)存區(qū)域之一,使用new和delete來予以分配和釋放(freed)。在自由存儲區(qū)(free ???store)中,對象的生存周期可以比存放它的內(nèi)存區(qū)的生存周期短;這也就是說,我們可以獲得一片內(nèi)存區(qū)而不用馬上對其進行初始??化;同時,在對 象被銷毀之后,也不用馬上收回其占用的內(nèi)存區(qū)。在對象被銷毀而其占用的內(nèi)存區(qū)還未被收回的這段時間內(nèi),我們可以??通過void*型的指針訪問這片區(qū)域, 但是其原始對象的非靜態(tài)成員以及成員函數(shù)(即使我們知道了它們的地址)都不能被訪問或者操??縱。
??
??[堆(heap)區(qū):]
?? 堆(heap)區(qū)是另一個動態(tài)存儲區(qū)域,使用malloc、free以及一些相關變量來進行分配和回收。要注意,雖然在特定的編譯器里缺省的??全局運? 算符new和delete也許會按照malloc和free的方式來被實現(xiàn),但是堆(heap)與自由存儲區(qū)(free store)是不同的——在某??一個區(qū)域內(nèi)被分配的內(nèi)存不可能在另一個區(qū)域內(nèi)被安全的回收。堆(heap)中被分配的內(nèi)存一般用于存放在使用new的構 造過程中和顯??式(explicit)的析構過程中涉及到的類對象。堆中對象的生存周期與自由存儲區(qū)(free store)中的類似。
??[全局/靜態(tài)區(qū)(Global/Static):]
?? ??全局的或靜態(tài)的變量和對象所占用的內(nèi)存區(qū)域在程序啟動(startup)的時候才被分配,而且可能直到程序開始執(zhí)行的時候才被初始??化。比如,函數(shù) 中的靜態(tài)變量就是在程序第一次執(zhí)行到定義該變量的代碼時才被初始化的。對那些跨越了翻譯單元(translation ???unit)的全局變量進行初始化操作的順序是沒有被明確定義的,因而需要特別注意管理全局對象(包括靜態(tài)類對象)之間的依賴關系。??最后,和前面 講的一樣,全局/靜態(tài)區(qū)(Global/Static)中沒有被初始化的對象存儲區(qū)域可以通過void*來被訪問和操縱,但是只要是??在對象真正的生存 周期之外,非靜態(tài)成員和成員函數(shù)是無法被使用或者引用的。
??
??[關于“堆(heap)vs.自由存儲區(qū)(free store)”]:
??本條款中我們將堆(heap)和自由存儲區(qū)(free store)區(qū)分開來,是因為在C++標準草案中,關于這兩種區(qū)域是否有聯(lián)系的問題一直??很謹慎的沒有予以詳細說明。比如當內(nèi)存在通過delete運算符進行回收時,18.4.1.1中說道:
???It is unspecified under what conditions part or all of such reclaimed storage is allocated by a ????subsequent call to operator new or any of calloc, malloc, or realloc, declared in <cstdlib>.
???[關于在何種情況下,這種內(nèi)存區(qū)域的部分或全部才會通過后續(xù)的對new(或者是在<cstdlib>里聲明的calloc,malloc,????realloc中的任何一個)的調(diào)用來被分配的問題,在此不作詳細規(guī)定,不予詳述。]
?
?????? 同樣,在一個特定的實現(xiàn)中,到底new和delete是按照malloc和free來實現(xiàn)的,或者反過來malloc和free是按照new和 delete來實現(xiàn)??的,這也沒有定論。簡單地說吧,這兩種內(nèi)存區(qū)域運作方式不一樣,訪問方式也不一樣——所以嘛,當然應該被當成不一樣的兩個東西?? 來使用了!
?
?Item 37: AUTO_PTR
??略
?Item 38 Object Identity
?(1): 千萬別寫一個依賴于檢測自身賦值達到正確操作的operator=(),一個拷貝賦值操作符應當使用create-a-temporary-and-swap
??方法來自動維持強異常安全和安全的自身賦值;
?
?(2): 自身賦值是個可行的優(yōu)化去避免無用的工作;
?
?Item 39 Automatic Conversions
?
?(1): 避免使用隱式轉換操作符:
??a: 隱式轉換會影響重載決議;
??b: 隱式轉換會讓錯誤的代碼安靜的編譯通過;
?(2):?C++標準保證「對指向同一個對象的多個指針的比較之結果必須是“相等(equal)” 」,但卻并不保證「對指向不同對象的多個指針??的比較之結果必須是“不相等(unequal)”」。
?Item 40,41 Object Lifetimes
?
?(1):?void f()
??{
???T t(1);
???T& rt = t;
???//#1 ?do something;
???t.~T();
???new (&t) T(2);
???//#2 ?do something;
??};
?a: #2是合法的;
?b: #2是不安全的;
?請總是嘗試寫異常安全級別的代碼, 總是嘗試正確的組織代碼讓資源正確的申請和釋放當異常拋出時;
?
?(2): 避免C++ 語言級別定義不太明確的技巧,應該多用清晰簡單的編程技巧;???
?(3): 用同一個成員函數(shù)完成兩種拷貝操作(拷貝構造和拷貝賦值)的注意是很好的:這意味著我們只需在一個地方編寫和維護操作代碼。本條??款問題中的慣用法只不過是選擇了錯誤的函數(shù)來做這件事。如此而已。
?
??其實,慣用法應該是反過來實現(xiàn)的:拷貝構造操作應該以拷貝賦值操作來實現(xiàn),不是反過來實現(xiàn)。例如:
??T::T( const T& other ) {
??????? /* T:: */ operator=( other );
??}
??? ??
??T& T::operator=( const T& other ) {
?????? ?// 真正的工作在這里進行
????? ??// (大概可以在異常安全的狀態(tài)下完成,但現(xiàn)在
????? ??// 其可以拋出異常,卻不會像原來那樣產(chǎn)生什么不良影響
???? ?? ?return *this;
??? ??}
??這段代碼擁有原慣用法的所有益處,卻不存在任何原慣用法中存在的問題。[注5] 為了代碼的美觀,你或許還要編寫一個常見的私有輔??助函數(shù),利用其做真正的工作;但這也是一樣的,無甚區(qū)別:
??? ??T::T( const T& other ) {
????? ??do_copy( other );
??? ??}
??? ??
??T& T::operator=( const T& other ) {
????? ??do_copy( other );
????? ??return *this;
??? ??}
??? ??
??T& T::do_copy( const T& other ) {
????? ??// 真正的工作在這里進行
????? ??// (大概可以在異常安全的狀態(tài)下完成,但現(xiàn)在
????? ??// 其可以拋出異常,卻不會像原來那樣產(chǎn)生什么不良影響
??}
?
?

??如果需要的話,請編寫一個私有函數(shù)來使拷貝操作和拷貝賦值共享代碼;千萬不要利用「使用顯式的析構函數(shù)并且后跟一個 placement ??new」的方法來達到「以拷貝構造操作實現(xiàn)拷貝賦值操作」這樣的目的,即使這個所謂的技巧會每隔三個月就在新聞組中出現(xiàn)幾次。??(也就是說,決不要 編寫如下的代碼:)
??????? ?T& T::operator=( const T& other )
??????? ?{
??????????? ?if( this != &other)
??????????? ?{
??????????????? ??this->~T();???????????? // 有害!
??????????????? ??new (this) T( other );? // 有害!
??????????? ?}
??????????? ?return *this;
??????? ?}
?

?Item 42: Variable Initialization -- Or is it?
?(1): 關于 T u; T t = u;
??這時,編譯器總會是調(diào)用 copy-construct而不是調(diào)用默認constructor之后調(diào)用operator=(),這只是一個從C繼承來的語法,???并沒有賦值操作
?(2): 用 T t(u);代替 T t = u;

?Item 43 Const-Correctiness;
?(1): 避免在某個函數(shù)參數(shù)使用 const by value
?(2): 如果是非內(nèi)部類型的return by value,那么優(yōu)先考慮返回一個const value;
?(3): 如果某個類數(shù)據(jù)成員的改變并不影響到類狀態(tài)的改變,例如class X { private: char buffer[1024]; ...};
??那么當某函數(shù)只改變這個類數(shù)據(jù)成員,而不改變其他成員時,也應當把這個函數(shù)為const ,并將這個被改變但無關類狀態(tài)的成員聲明為
??mutable;

?Item 44 Casts
?(1): 請優(yōu)先使用新轉型風格cast;
?(2): 避免用const_cast消除const ,請優(yōu)先使用mutable;
?(3): 避免動態(tài)的向下轉型;
?Item 45: BOOL
?略
?Item 46 Forwarding Functions;
?(1): 多考慮傳遞對象的const &;
?(2): 避免語言的隱晦角落,多用簡單的技巧;
?(3): 如果不認為性能上絕對需要,請避免inline或者內(nèi)部優(yōu)化;

?Item 47 Control Flow
?(1): 避免使用全局或者靜態(tài)變量;如果必須如此,那么請注意它們的初始化順序(因為多個頭文件內(nèi)引入的靜態(tài)變量的聲明順尋并不是標準定??義的);
?(2): 將基類的constructor在初始化器列表中的順序和類聲明的順序是一樣的,基類的初始化順序是依據(jù)類定義時的順序的;
?(3): 將類的數(shù)據(jù)成員的初始化順序與初始化器列表中聲明的順序是一樣的,同樣依據(jù)類定義;
?(4): 努力去實現(xiàn)代碼的異常級安全;
?(5): 絕不能寫依賴函數(shù)參數(shù)賦值順序的代碼;