C++學習筆記(轉)
阿新 • • 發佈:2019-02-15
1.struct成員預設訪問方式是public,而 class預設訪問方式是private! 2.exit函式終止程式執行會呼叫解構函式 ,abort函式終止程式不會呼叫解構函式! 3.靜態區域性變數直到程式終止時才退出! 4.通過public 函式返回 private成員的引用有可能會破壞類的封裝 ,造成外部變數可以改變類私有成員值! 5.常量物件只能呼叫常量成員函式,常量成員函式可以有非常量版本過載! 6.常量資料成員只能在定義時初始化或者在建構函式裡用成員初始化值來初始化 ,不能用賦值語句來初始化! 7.要在解構函式裡面使用delete來釋放使用 new申請的記憶體空間!8.編寫解構函式來釋放類中成員所申請的記憶體空間和使用深拷貝函式是好的程式設計習慣! 9.operator++()是相當與++d,operator++(int) 是相當於 d++ ! 10.如果父類中函式是虛擬函式 ,那麼在每個子類中顯式宣告虛擬函式是好的程式設計習慣! 11.如果類作為基類,其解構函式要宣告為虛解構函式 ,這樣派生類才可以呼叫自己的解構函式! 12.一個new 就對應一個 delete是好的程式設計習慣! 13.istream輸入read 是從檔案中讀取 ,ostream輸出write 是寫到檔案中去! 14.istream是seekg 重置檔案指標位置 ,ostream是seekp, 檔案用file.eof()來判斷是否讀取到檔案尾部!15.assert(條件), 當滿足條件時就不 assert,不滿足條件才會assert! 16.對於不需要修改的變數,使用常量引用來傳遞引數可以既保證安全性又保證效率! 17.在迴圈之前呼叫srand(time(0)),然後在迴圈中呼叫 rand()函式可以使得每次隨機的結果都不相同! 18.一維陣列形參如下:int a[],二維陣列形參如下 :int a[][SIZE],第一個[] 是空的,後面必須非空! 19.#define A 10 後面沒有分號! 20.在區域性函式中用new建立的變數是存在記憶體中的,即便區域性函式執行完畢記憶體變數仍然存在,但是指向它的指標有可能是區域性變數,則需要在區域性函式結束前呼叫 delete釋放記憶體空間,以免記憶體洩漏21.陣列宣告最好用 T *a 來宣告 ,這樣不容易出錯,建立物件最好用 new 而不是直接建立! 22.定義一個類時,解構函式(釋放資源)和拷貝建構函式(深拷貝)最好顯示定義! 23.C/C++語言輸入結束符是ctrl+z(windows下 )! 24.C語言的printf(“%.9lf”,a); 比c++的 setprecision(10)來的更加精確,C++有時自動舍入精度! 25.理清狀況,邏輯嚴謹,變數初始化、是還是否、邊界判斷判斷正確! 26.要使得棧中的基本元素是模板類型別,必須要定義模板類的一些函式:預設建構函式,友員輸出函式等! 27.用單件模式和全域性函式替代全域性變數,以便於拓展和維護! 28.用const char *ptr 表示ptr指向的變數為常量。 char* const ptr表明ptr 本身為常量是好的程式設計習慣! 29.const int *i = &a, 只是代表不能通過 i指標來修改,但是可以通過其它途徑來修改 a,例如a=3 ! 30.靈活熟練運用語言,如 (a<b?a:b<c?b:c) = val();這句話就將3 個if語句合併成一句話! 31.橋接模式bridge 可以實現介面與實現分離 ,這樣可以減少修改類時需要修改的類的範圍! 32.優先順序:i++ 高於 ++i ,注意,具體運算子優先順序看下面的運算子優先順序表! 33.遞迴演算法符合大致演算法思想就行了 ,不必深究思考,合理就可以了! 34.在C++ 中使用0來對指標初始化可以保證數字字面常量 0可以轉換成任何一種指標型別對應的空指標! 35.非const 物件可以呼叫 const和非const 函式,但是 const物件只能呼叫const函式! 36.可以使用非const 型別變數賦給 const型別引數,不能用const型別變數賦值給非 const型別引數! 37.類過載二元運算子時,要麼作為類的只帶一個引數的內部函式 ,要麼作為類中帶兩個引數的友元函式! 38.內建的operator-> 是二元的 ,而過載的operator-> 是一元的 ,如果過載了operator-> 則先呼叫過載的 ,直到重複呼叫到內建的operator->才終止! 39.儘量使用STL 是好的程式設計習慣! 40.++i返回的是記憶體變數,可以作為左值也可以作為右值 ,而i++ 返回的是字面量 ,不佔記憶體, 不能作為左值右值! 41.for迴圈中使用continue 不會出現死迴圈 ,但是while 中使用continue容易出現死迴圈 ,因為可能i 沒有自加! 42.取最大優先分析原則會取最長的型別 ,所以要這麼義:list<vector<string> > lovos;右邊兩個>> 之間必須有空格 ,如果沒有則編譯器可能解釋成 >>右移操作符! 43.對於平凡整型常量,可以用列舉量來表示! 44.派生類賦值給基類是不要使用物件繼續賦值 ,而是使用指標或引用以避免發生截切! 45.不使用 void * 為型別轉換的中介型別是良好的程式設計習慣 ,因為void * 會抹除指標的型別資訊! 46.使用引用型別或標準庫元件以避免引入多級指標的複雜性是較佳的設計! 47.在類物件中儘量避免使用二級指標 ,尤其是在基類指向派生類物件的指標時尤其要注意! 48.在C++ 類中儘量不要過載型別轉換 operator函式, 而是使用有明確含義的如 toInt(),toChar()等函式替代! 49.C++中有時在類建構函式前加上 explicit關鍵字來禁止隱式型別轉換可以減少很多錯誤! 50.多用引用傳遞引數,用值傳遞時會有大量的複製操作 ,效率很低, 多用引用是好的程式設計習慣! 51.函式物件就是過載了operator()的 class物件, 使用函式物件生成匿名臨時物件是好的程式設計習慣! 52.使用dynamic_cast<>,static_cast<>,const_cast<>,reinterpret_cast<> ! 53.在派生類建構函式中儘量多使用成員初始化列表 ,靜態資料成員和陣列不允許在成員初始化表中進行初始化 ,可以在函式體中進行初始化! 54.在類中涉及到指標和引用等 ,最好顯示撰寫深拷貝建構函式和賦值運算子過載 operator=(),以免出現錯誤! 55.子類在繼承父類時如果重寫父類的虛擬函式或者非虛擬函式 ,要保證在子類中重寫的函式訪問修飾符和父類結合繼承訪問後得到的訪問修飾符結果一致! 56.在寫拷貝建構函式和重寫賦值運算子函式時必須把類中所有變數都用 '='號顯示寫全了,不要寫一部分 ,如果你沒寫, 則編譯器只會呼叫預設建構函式進行變數初始化 ,而不會預設用'='號! 57.儘量不要在類中使用靜態變數 ,永遠不要做執行期靜態初始化! 58.對class 物件或者有可能是 class物件的實體進行直接初始化而不是用賦值語句初始化 ,如:N n(0)! 59.搞清楚複製初始化和賦值初始化的不同 ,複製初始化是呼叫拷貝建構函式實現 ,而賦值是過載'='實現! 60.可以通過在private 區域宣告拷貝建構函式來禁止類的複製初始化! 61.物件作為引數儘量使用引用傳遞 ,其次考慮指標,儘量不要用值傳遞 ,如果不想修改物件可以加 const! 62.丟擲匿名臨時異常物件,並以引用的方式捕獲它們 ,如需重新丟擲,則丟擲既有的異常物件 ,而非處理原始的異常之後 ,丟擲一個新的異常物件! 63.不要返回函式作用域內所分配的儲存的引用(返回指標或直接傳值可以) ,會造成記憶體洩漏! 64.使用類的建構函式和解構函式來封裝一些成對的操作如加鎖和解鎖等 ,這樣在函式執行開始時建立類物件 ,使用A a; 而不適A a();或 A()來建立, 在函式結束前會自動刪除改物件 ,也就實現了開始時呼叫加鎖操作 ,結束時呼叫解鎖操作,俗稱 RAII(資源獲取即初始化)! 65.複製auto_ptr 模板例項化物件將指向的物件的控制權轉移 ,然後把複製源設為空! 66.永遠不要把auto_ptr 例項化的型別作為 STL容器的基本型別! 67.不要將auto_ptr 物件作為函式引數按值傳遞 ,會清空原有物件,造成不可預知的錯誤! 68.不要在虛擬函式中提供引數的預設初始化物! 69.訪問層級(public protected private) 對重寫虛擬函式沒有任何影響 ,即使public 繼承,你也可以將繼承過來的本來應該是 public的函式寫到private 作用域中 ,完全可以! 70.派生類中對基類中的非虛擬函式的重寫或過載其實是遮掩 ,會將基類中同名的所有虛擬函式和非虛擬函式全部遮掩 ,使之無效, 這時想要構成過載 ,必須使用using A::fun() 函式來匯入基類中 fun函式! 71.過載必須在同一個類作用域下才構成過載 ,否則只是遮掩! 72.過載虛擬函式要麼對基類中的每一個都重寫要麼一個都不要重寫 ,或者使用using A::fun() ! 73.C++中儘量避免使用指標,而是使用引用! 74.複製操作不經由模板成員函式來實現 ,必須顯示給出複製操作的實現! 75.使用者自定義版本的後置式形式自增自減運算子應該返回常量 ,因為後置後置不能作為左值! 76.前置式總是優於後置式,即 ++i總是優於i++ ! 77.非成員友員允許在第一個引數上施行型別轉換 ,而成員函式不能在第一個引數上施行型別轉換! 78.在進行指標重新複製時一定要注意是否可能造成記憶體洩漏 ,是否要先釋放當前指標所指記憶體空間! 79.mutable變數可以在const 函式中被修改 ,其效果好於const_cast<>, 所以儘量使用 mutable! 80.類過載運算子時有時必須引數和函式都是 const,這樣保證在其他函式呼叫時即使傳遞常量引數也沒問題! 81.變數傳遞給常量引數可以 ,但是常量傳遞給變數引數卻不行! 82.多使用虛擬函式實現不同的功能 ,把基類儘量細分成更小的基類! 83.使用動態繫結而不是條件式的分派實現型別相關的需求! 84.如果某個型別可能成為基類 ,則一開始就把它寫成抽象基類! 85.以public 方式繼承的基類一般應該是抽象的 ,應該集中精力於介面繼承而不是程式碼複用! 86.介面類就是沒有資料成員 ,解構函式宣告為虛擬函式,普通成員函式皆為純虛擬函式 ,不宣告建構函式的型別! 87.要麼public, 要麼友元函式 ,其它如protected 繼承後的函式交叉呼叫可能會出現問題! 88.儘量不使用class 陣列,多用 STL容器, 如vector,而且容器型別是指標而不是物件 ,如vector<B *>! 89.wget w1 = w2;呼叫拷貝建構函式,而 wget w1;w1 = w2;呼叫的是類賦值運算子! 90.類引數傳值傳遞是呼叫拷貝建構函式 ,多用const 引用! 91.enum{star=5};這裡定義的star 可以當作常量字面量來用 ,和#define star 5 效果是一樣的! 92.儘量使用const,enum,inline 來代替#define,使用模板 inline函式代替巨集! 93.對於單純常量,最好用 const和enum 代替#define,對於形似函式的巨集 ,最好使用inline 函式來替代! 94.如果const 出現在*左邊則所指的是常量 ,如果const 出現在*右邊 ,則指標是常量! 95.STL中const vector<int>::iterator 相當於T*const,vector<int>::const_iterator相當於const T* ! 96.函式的const 版本可以和原版本過載 ,用非const 函式呼叫 const函式可以減少程式碼重複! 97.使用函式返回靜態物件將 non-local static物件轉化為locat static 物件! 98.引用的賦值相當於把等號右邊別名所指的物件值替換了等號左邊別名所指物件的值,還是 2個物件! 99.可以通過宣告純虛解構函式來定義一個抽象類 ,這時純虛解構函式必須給出定義才行! 100.解構函式絕對不要吐出異常 ,即使出現異常也要在解構函式內部處理 ,要麼結束要麼吞下! 101.不要在建構函式和解構函式中呼叫 virtual函式, 不會下降到 derived class類別, 用向上傳遞引數替換! 102.令賦值操作符返回一個reference to *this ! 103.派生類中的拷貝建構函式和賦值符號不會自動拷貝或賦值基類部分 ,所以要顯示呼叫基類拷貝或賦值函式! 104.在釋放記憶體空間時先把原指標所指記憶體區域備份 ,再刪除或指向新的記憶體空間 ,再delete 原來備份的區域! 105.多使用tr1::shared_ptr 和auto_ptr智慧指標來自動釋放記憶體空間! 106.類中儘量不要定義型別轉換符號 ,即使定義也沒有返回型別 ,因為型別轉換符本身已經規定了返回型別! 107.shared_ptr物件如果有多個指向一個指標 ,則只有第一個需要使用指標初始化 ,其他的要麼用拷貝建構函式 ,要麼用賦值運算子初始化 ,指標初始化只能用一次! 108.對於內建型別、STL和函式物件 ,傳值比較高效,但是對於其它型別 ,傳遞常量引用比較高效! 109.引用和指標一樣支援多型性 ,因為引用的內部就是通過指標實現的! 110.儘量用non-member 和non-friend函式替換 member函式! 111.如果一個函式和類相關,但不是成員函式 ,那麼該函式也不一定非得是友元函式 ,如果函式能通過類的公共介面完成功能 ,則完全不必宣告為友元函式 ,但該函式返回值一般是const! 112.建構函式如果不是explicit則可以進行隱式型別轉換 ,不管建構函式有幾個引數 ,但前提是如果你給的實際引數個數小於建構函式需求引數個數 ,你得保證建構函式有預設構造引數! 113.一個類內物件內部函式可以訪問物件自己的私有成員變數 ,但是如果有一個同類的另一個物件作為函式的引數 ,則該內部函式也可以訪問另一個物件的私有成員變數! 114.儘量往後定義變數的出現 ,最好能等到變數不僅需要被使用而且初值也確定時再定義! 115.儘量避免使用轉型,即使必須使用也得使用 C++特定的如static_cast 等! 116.虛解構函式都是public,沒有其它的像 private和protected 型別的! 117.根據實際需要選準模式,是 is-a 還是has-a,private 繼承和has-a類似 ,但是一般都是會選擇has-a! 118.因為private 繼承不是 is-a關係, 所以不能滿足基類指標指向派生類的情況 ,當然不能使用多型性,只能看作是和 has-a一樣的情況了! 119.virtual函式即使是private 函式且被 private繼承, 雖然對於派生類不可訪問 ,但派生類還是可以繼承基類 virtual函式並重寫的,並無影響! 120.指標可以改變其指向的物件 ,但是引用不行,引用一旦賦值後不能改變! 121.過載某個操作符時應該返回引用而不是指標! 122.隱式轉換最多隻能轉換一次 ,超過一次就被禁止! 123.字首返回引用,字尾返回 const value,字尾通過字首實現,字首效率比字尾高! 124.在解構函式中釋放資源,儘量使用引用來捕捉異常 ,而不用傳值或指標! 125.模板和異常規格不要混合使用 ,異常規格是一個應該被審慎使用的特性! 126.STL中對於iterator 儘量運用 (*iterator).first來取值, 而不是用 ->來取值! 127.C++禁止為非常量引用建立臨時變數 ,所以非常量引用傳遞引數時不會發生隱式型別轉換! 128.常量引用是會建立臨時變數的 ,這時會發生隱式型別轉換! 129.每一個過載運算子必須自帶至少一個使用者自定義型別的引數! 130.操作符 -> 優先順序高於 * ! 131.每種類有一個vtbl,每個物件有一個 vptr,RTTI是在vtbl 中增加一項 ,所以只會增加類大小,而不會增加物件大小! 132.解構函式必須被定義! 133.auto_ptr物件最好使用const引用傳遞 ,而不要用值傳遞! 134.編譯器只能預設幫你進行一次型別轉換 ,超過一次就不行! 135.對靈巧指標絕對不要提供一個轉換到原始指標型別的轉換操作符! 136.當使用型別轉換太麻煩時 ,不妨就使用模板吧! 137.一定要為含有指標的類提供深拷貝建構函式 ,以免在以後的運用中出現錯誤! 138.建構函式和解構函式可以被子類繼承 ,但如果解構函式是虛擬函式 ,繼承的子類的解構函式也預設是虛擬函式 ,但你最好加上virtual增加可讀性! 139.cout<<setiosflags(ios::fixed)<<setprecision(n)<<s1<<endl; 用來設定 C++中輸出小數點後位數! 140.使用extern “C” 可以將函式變成 c函式風格, 即obj檔案中不能進行名變換! 141.將十進位制化為二進位制或判斷能否被 2整除或者除以2可以使用右移操作和 &1操作! 142.C++和C語言中,把整數賦值給字元變數,是將整數當作ASCII碼賦給字元變數,將字元變數賦值給整數也是將字元變數對應的ASCII碼賦給整數! 143.C++中STL容器的工作方式是對內建型別是位拷貝,自定義物件是存入物件的拷貝,使用insert或是push_back時都是使用拷貝,如果建立物件時是在堆中,則傳指標給STL,如果在棧中,則傳遞物件本身! 144.C++中使用STL容器時,若物件拷貝動作較多,基類又要記錄派生類,則存放指標,若是基本型別或者很少拷貝,則存放物件!