例100篇:從基礎(chǔ)語(yǔ)法到STL算法的完整編譯實(shí)戰(zhàn)指南)
簡(jiǎn)介編程學(xué)習(xí)的關(guān)鍵在于動(dòng)手實(shí)踐而C作為系統(tǒng)級(jí)開(kāi)發(fā)語(yǔ)言其語(yǔ)法特性和標(biāo)準(zhǔn)庫(kù)設(shè)計(jì)對(duì)初學(xué)者存在一定門檻。理解變量、控制流、函數(shù)等基礎(chǔ)概念后如何通過(guò)完整可編譯的實(shí)例代碼鞏固知識(shí)并掌握類設(shè)計(jì)、STL容器、算法與文件操作等進(jìn)階技能是每個(gè)C學(xué)習(xí)者面臨的共同問(wèn)題。本文從工程實(shí)踐角度切入介紹一份涵蓋100例可獨(dú)立編譯源碼的資源解析基礎(chǔ)層、進(jìn)階層與算法層的代碼結(jié)構(gòu)說(shuō)明g編譯參數(shù)、調(diào)試器定位段錯(cuò)誤等實(shí)用技能并分享迭代器失效、內(nèi)存泄漏等常見(jiàn)踩坑經(jīng)驗(yàn)。通過(guò)重組實(shí)例索引、添加基準(zhǔn)測(cè)試等方式讀者可將示例代碼沉淀為個(gè)人模板庫(kù)提升面試準(zhǔn)備與日常開(kāi)發(fā)效率。1. C編程實(shí)例100篇刷題之外為什么還需要一本能直接編譯的實(shí)例集C學(xué)了語(yǔ)法不等于會(huì)寫程序這是我反復(fù)跟身邊人強(qiáng)調(diào)的一句話。書店里講C的書動(dòng)輒七八百頁(yè)習(xí)題答案卻往往只給核心代碼段缺頭文件、缺main函數(shù)、缺邊界處理抄到本地一編譯全是錯(cuò)。這份C編程實(shí)例100篇的資源好就好在每一個(gè)實(shí)例都是完整可編譯的獨(dú)立程序從經(jīng)典冒泡排序到STL容器操作再到文件讀寫全部自帶注釋和main入口下載解壓后配合g或Visual Studio就能直接跑。它適合兩類人一類是剛學(xué)完語(yǔ)法、想靠大量代碼練習(xí)鞏固基礎(chǔ)的新手另一類是面試前需要快速過(guò)一遍高頻考點(diǎn)、手里缺一份現(xiàn)成代碼倉(cāng)庫(kù)的從業(yè)者。接下來(lái)我按拆解的真實(shí)體驗(yàn)說(shuō)說(shuō)這里面的構(gòu)成、編譯方法、踩過(guò)的坑以及怎么把它變成自己的資源。2. 實(shí)例庫(kù)分層拆解基礎(chǔ)語(yǔ)法、STL與算法三個(gè)層面各解決什么問(wèn)題把100篇實(shí)例當(dāng)作一個(gè)整體來(lái)看很容易陷入不知道從哪一篇開(kāi)始的窘境。我拿到手之后先做了個(gè)粗分類發(fā)現(xiàn)這份資源并不是隨機(jī)堆疊而是有明顯分層最前面是基礎(chǔ)語(yǔ)法和流程控制中間是函數(shù)、類和對(duì)象后面是STL容器、算法和文件操作。理解這個(gè)分層比直接從頭刷更有效率。2.1 實(shí)例編號(hào)與分類標(biāo)簽從100個(gè)文件里找出你需要的那個(gè)每個(gè)實(shí)例文件命名都有規(guī)律比如ex001_bubble_sort.cpp、ex052_student_class.cpp、ex088_file_wordcount.cpp編號(hào)加短橫線加英文描述。命名里帶主題詞用編輯器打開(kāi)目錄后可以按關(guān)鍵詞快速篩選。我一般會(huì)先做一次整理按知識(shí)點(diǎn)把100個(gè)文件分成基礎(chǔ)語(yǔ)法、控制流、函數(shù)、類與對(duì)象、STL容器、算法、文件操作、字符串處理八類每類建一個(gè)索引表記錄實(shí)例編號(hào)、功能簡(jiǎn)述和核心知識(shí)點(diǎn)。表格比記在腦子里有用的多我自己的檢索表長(zhǎng)這樣分類實(shí)例編號(hào)核心知識(shí)點(diǎn)難度基礎(chǔ)語(yǔ)法ex001-ex015變量、類型轉(zhuǎn)換、運(yùn)算符入門控制流ex016-ex025分支、循環(huán)、跳轉(zhuǎn)入門函數(shù)與遞歸ex026-ex035參數(shù)傳遞、遞歸、重載基礎(chǔ)類與對(duì)象ex036-ex055構(gòu)造析構(gòu)、封裝、繼承基礎(chǔ)STL容器ex056-ex075vector/map/string/set進(jìn)階算法與排序ex076-ex090冒泡、快排、二分查找進(jìn)階文件與IOex091-ex100流操作、二進(jìn)制讀寫進(jìn)階2.2 基礎(chǔ)層實(shí)例分析變量、循環(huán)、函數(shù)的推進(jìn)節(jié)奏與教學(xué)意圖前15個(gè)實(shí)例基本在解決一件事讓初學(xué)者養(yǎng)成先聲明再使用的肌肉記憶。實(shí)例ex007是一個(gè)經(jīng)典的是素?cái)?shù)判斷程序它的教學(xué)重點(diǎn)不是算法本身而是函數(shù)分離和布爾返回值的使用。#include iostream #include cmath bool isPrime(int n) { if (n 2) return false; for (int i 2; i std::sqrt(n); i) { if (n % i 0) return false; } return true; } int main() { for (int num 2; num 100; num) { if (isPrime(num)) { std::cout num ; } } std::cout std::endl; return 0; }這個(gè)寫法有兩個(gè)值得注意的地方。第一函數(shù)返回布爾值而不是打印結(jié)果把判斷和輸出分離這是后續(xù)所有復(fù)雜實(shí)例的基礎(chǔ)結(jié)構(gòu)。第二循環(huán)上界用std::sqrt(n)而不是n/2避免無(wú)謂迭代。對(duì)于初次接觸這份資源的人建議不要只編譯通過(guò)就完事而是手動(dòng)把sqrt改成n/2重新跑一次并記錄兩者的性能差異這會(huì)讓你對(duì)算法復(fù)雜度產(chǎn)生實(shí)感。2.3 進(jìn)階層實(shí)例分析字符串處理與STL容器的組合用法實(shí)例ex088是一個(gè)詞頻統(tǒng)計(jì)程序它把文件讀取、字符串清洗和map容器組合在一起一次性展示了三個(gè)知識(shí)點(diǎn)的配合方式。我復(fù)現(xiàn)它的過(guò)程里最大的收獲是理解了為什么把臟數(shù)據(jù)清洗放在插入容器前。#include iostream #include fstream #include map #include string #include cctype int main() { std::ifstream input(sample.txt); if (!input.is_open()) { std::cerr 文件打開(kāi)失敗 std::endl; return 1; } std::mapstd::string, int freq; std::string word; while (input word) { // 去掉單詞首尾的非字母字符 while (!word.empty() !std::isalpha(word.front())) { word.erase(word.begin()); } while (!word.empty() !std::isalpha(word.back())) { word.pop_back(); } if (!word.empty()) { freq[word]; } } for (const auto entry : freq) { std::cout entry.first : entry.second std::endl; } return 0; }參數(shù)說(shuō)明is_open()用于確認(rèn)文件流狀態(tài)防止在文件不存在時(shí)繼續(xù)執(zhí)行isalpha逐字符判斷字母pop_back和erase都是在原字符串上操作不產(chǎn)生額外拷貝。這里有個(gè)常見(jiàn)誤區(qū)是直接把input word的結(jié)果塞進(jìn)map那樣的話Hello,和Hello會(huì)被當(dāng)成兩個(gè)單詞。這個(gè)實(shí)例的價(jià)值就在于它提前給出了清洗層的實(shí)現(xiàn)思路我后來(lái)遇到類似文本處理需求時(shí)第一反應(yīng)就是復(fù)用這個(gè)結(jié)構(gòu)。2.4 算法層實(shí)例分析排序、查找與遞歸的代碼風(fēng)格從ex076開(kāi)始實(shí)例偏向算法實(shí)現(xiàn)。值得注意的是這里的排序和查找代碼并不完全是經(jīng)典教材寫法它們更貼近實(shí)際編碼風(fēng)格用std::vector代替裸數(shù)組用迭代器范圍代替長(zhǎng)度參數(shù)。以二分查找為例典型的實(shí)例實(shí)現(xiàn)會(huì)用模板函數(shù)配合迭代器而不是把數(shù)組和大小綁定在一起。#include iostream #include vector #include algorithm template typename T int binarySearch(const std::vectorT vec, const T target) { int left 0; int right static_castint(vec.size()) - 1; while (left right) { int mid left (right - left) / 2; if (vec[mid] target) return mid; if (vec[mid] target) left mid 1; else right mid - 1; } return -1; } int main() { std::vectorint data {1, 3, 5, 7, 9, 11, 13}; int index binarySearch(data, 7); std::cout 找到下標(biāo): index std::endl; return 0; }left (right - left) / 2這行是關(guān)鍵它避免了(left right)在數(shù)值較大時(shí)溢出這是很多教材不寫的細(xì)節(jié)。模板參數(shù)T讓函數(shù)可以同時(shí)處理int、double、string等類型實(shí)用性比硬編碼int高得多。建議在復(fù)現(xiàn)時(shí)試著把std::vectorT改成std::listT你會(huì)看到編譯直接報(bào)錯(cuò)這是因?yàn)閘ist不支持隨機(jī)訪問(wèn)迭代器這個(gè)報(bào)錯(cuò)本身就是很好的學(xué)習(xí)素材。3. 把實(shí)例跑起來(lái)編譯命令、調(diào)試切入點(diǎn)與一次改造練習(xí)拿到源碼之后最大的攔路虎往往不是代碼本身而是怎么編譯、怎么運(yùn)行、報(bào)錯(cuò)了怎么查。這一章我把實(shí)際跑完100個(gè)實(shí)例時(shí)最常用的命令和排查手法列出來(lái)覆蓋命令行和IDE兩種場(chǎng)景。3.1 命令行編譯的標(biāo)準(zhǔn)姿勢(shì)g參數(shù)逐個(gè)拆解實(shí)例大部分是單文件程序用g編譯是最直接的方式。我推薦固定使用以下命令不要在編譯選項(xiàng)上隨意偷懶g(shù) -stdc11 -Wall -Wextra -O2 -g -o wordfreq wordfreq.cpp各參數(shù)含義如下-stdc11指定C版本實(shí)例中個(gè)別代碼用到auto和范圍for循環(huán)需要至少C11標(biāo)準(zhǔn)-Wall -Wextra打開(kāi)編譯警告很多隱患會(huì)在編譯期暴露比如有符號(hào)和無(wú)符號(hào)整數(shù)比較、未使用的變量等-O2開(kāi)啟優(yōu)化讓運(yùn)行結(jié)果接近生產(chǎn)環(huán)境-g生成調(diào)試信息后面用調(diào)試器排查時(shí)必須有它。如果程序里用了std::thread或std::mutex還需要追加-pthread選項(xiàng)這是初學(xué)者最容易漏的漏掉后表現(xiàn)為鏈接錯(cuò)誤提示找不到pthread_create相關(guān)符號(hào)。編譯失敗時(shí)先看第一條報(bào)錯(cuò)而不是最后一條因?yàn)镃模板報(bào)錯(cuò)經(jīng)常是連帶式的第一條才是真正的根因。我在實(shí)例ex063vector嵌套排序上就吃過(guò)這個(gè)虧看到后面一長(zhǎng)串模板錯(cuò)誤以為是自己代碼邏輯問(wèn)題結(jié)果只是忘了包含algorithm頭文件。3.2 運(yùn)行時(shí)錯(cuò)誤怎么查用調(diào)試器走一遍越界與崩潰編譯通過(guò)不代表程序正確。實(shí)例ex041是一個(gè)鏈表反轉(zhuǎn)程序我在復(fù)現(xiàn)時(shí)跑出了段錯(cuò)誤這種問(wèn)題靠加std::cout打印效率太低正確做法是用gdb定位。gdb ./ex041_segfault (gdb) run (gdb) backtrace (gdb) frame 3 (gdb) info locals (gdb) print node-next操作說(shuō)明run啟動(dòng)程序直到崩潰點(diǎn)backtrace打印調(diào)用棧能看到崩潰發(fā)生在哪個(gè)函數(shù)哪一行frame 3切換到第3層調(diào)用幀info locals查看當(dāng)前函數(shù)的局部變量print輸出某個(gè)指針的值比如node-next從而判斷是否為空指針或野指針。我在實(shí)際使用中發(fā)現(xiàn)段的錯(cuò)誤大多數(shù)時(shí)候不是邏輯難而是指針在某個(gè)分支里沒(méi)有初始化就進(jìn)入了循環(huán)。調(diào)試器給你的不是答案而是線索看清調(diào)用棧之后回到代碼里檢查那個(gè)分支條件問(wèn)題很快就暴露。3.3 實(shí)例改造練習(xí)把第52例擴(kuò)展成一個(gè)學(xué)生成績(jī)管理程序只看不練等于白下這份資源。我的習(xí)慣是挑一個(gè)實(shí)例做改造第52例是一個(gè)簡(jiǎn)單的學(xué)生類只有姓名和成績(jī)兩個(gè)字段功能是打印信息。我把它擴(kuò)展成一個(gè)帶排序和統(tǒng)計(jì)的最小管理系統(tǒng)整個(gè)過(guò)程只用到了實(shí)例庫(kù)里已經(jīng)出現(xiàn)過(guò)的知識(shí)點(diǎn)。#include iostream #include vector #include string #include algorithm class Student { public: Student(const std::string name, double score) : name_(name), score_(score) {} std::string name() const { return name_; } double score() const { return score_; } private: std::string name_; double score_; }; // 按成績(jī)從高到低排序 bool compareByScore(const Student a, const Student b) { return a.score() b.score(); } int main() { std::vectorStudent students; students.emplace_back(A同學(xué), 88.5); students.emplace_back(B同學(xué), 92.0); students.emplace_back(C同學(xué), 76.5); std::sort(students.begin(), students.end(), compareByScore); double total 0.0; for (const auto stu : students) { std::cout stu.name() : stu.score() std::endl; total stu.score(); } if (!students.empty()) { std::cout 平均分: total / students.size() std::endl; } return 0; }邏輯說(shuō)明emplace_back在容器尾部直接構(gòu)造對(duì)象避免臨時(shí)對(duì)象的拷貝compareByScore作為自定義排序函數(shù)傳給sort第三個(gè)參數(shù)指定排序規(guī)則范圍for循環(huán)加const auto避免了拷貝。這里我踩過(guò)一個(gè)很典型的坑忘記檢查students.empty()就直接除size()在空列表時(shí)輸出-nan這是運(yùn)行時(shí)邏輯問(wèn)題編譯器不會(huì)報(bào)錯(cuò)。從那以后凡涉及除法都先用保護(hù)條件確認(rèn)分母非零。4. 實(shí)例庫(kù)踩坑與排查刷完100例后記下的五條血淚經(jīng)驗(yàn)這章是全文最值錢的部分。實(shí)例庫(kù)本身是教學(xué)資源但教學(xué)資源的代碼并不意味著沒(méi)有坑有些坑恰恰是設(shè)計(jì)者故意留在里面等你發(fā)現(xiàn)的有些則是不同編譯器行為差異帶來(lái)的。我把五條印象最深、最容易復(fù)現(xiàn)的踩坑記錄放在這里每條都按現(xiàn)象、原因、解決的順序?qū)懬宄?.1 坑1字符串遍歷時(shí)越界程序不報(bào)錯(cuò)但結(jié)果詭異現(xiàn)象實(shí)例ex023字符去重統(tǒng)計(jì)在Windows上跑結(jié)果正確換到Linux上輸出多了一個(gè)空行。原因Windows文本換行是\r\nLinux是\n直接按字符讀取時(shí)\r被當(dāng)成一個(gè)普通字符進(jìn)了統(tǒng)計(jì)。解決讀取時(shí)統(tǒng)一清洗或者用std::getline按行讀取后手動(dòng)去掉行尾的\r。這個(gè)坑不算代碼邏輯錯(cuò)誤而是平臺(tái)差異但它讓我意識(shí)到跨平臺(tái)程序的第一課就是不要假設(shè)換行符長(zhǎng)一個(gè)樣。4.2 坑2指針與引用混用懸掛指針在release版才翻車現(xiàn)象實(shí)例ex034鏈表刪除節(jié)點(diǎn)在debug版運(yùn)行正常release版偶爾輸出隨機(jī)值。原因函數(shù)返回了局部變量的地址或者引用debug版內(nèi)存沒(méi)有立刻被覆蓋release版棧幀復(fù)用導(dǎo)致數(shù)據(jù)被改寫。解決檢查所有返回類型但凡返回的是引用或指針必須確認(rèn)指向的對(duì)象生命周期長(zhǎng)于返回值的使用周期。后來(lái)我用一個(gè)簡(jiǎn)單規(guī)則排查凡是函數(shù)體內(nèi)new出來(lái)的對(duì)象才適合返回裸指針棧上對(duì)象一律返回值而不是地址。4.3 坑3vector迭代器失效insert/erase之后繼續(xù)遍歷直接崩潰現(xiàn)象實(shí)例ex071按條件刪除vector元素在某些機(jī)器上偶發(fā)崩潰但每次崩潰的行號(hào)不一樣。原因erase操作會(huì)讓當(dāng)前迭代器和之后的所有迭代器失效直接對(duì)失效迭代器執(zhí)行操作屬于未定義行為。解決正確寫法是讓erase返回下一個(gè)有效迭代器即it vec.erase(it)或者配合std::remove_if加erase的組合手法一次性處理。std::vectorint data {1, 2, 3, 4, 5, 6, 7, 8}; // 錯(cuò)誤寫法 for (auto it data.begin(); it ! data.end(); it) { if (*it % 2 0) { data.erase(it); // 迭代器已失效it未定義行為 } } // 正確寫法 for (auto it data.begin(); it ! data.end(); ) { if (*it % 2 0) { it data.erase(it); } else { it; } }這是實(shí)例庫(kù)中少見(jiàn)的帶坑代碼我當(dāng)時(shí)排查了很久最后發(fā)現(xiàn)異?,F(xiàn)象的根本原因是對(duì)迭代器失效規(guī)則不熟悉。現(xiàn)在遇到容器刪除場(chǎng)景我第一反應(yīng)就是檢查是不是用了失效迭代器。4.4 坑4編譯器標(biāo)準(zhǔn)不同同一份代碼兩次編譯結(jié)果不一致現(xiàn)象實(shí)例ex082lambda表達(dá)式排序用g4.8編譯報(bào)錯(cuò)換g9之后就正常。原因不同的C標(biāo)準(zhǔn)對(duì)lambda表達(dá)式的支持細(xì)節(jié)有差異早期版本不支持某些捕獲方式。解決統(tǒng)一用-stdc11或-stdc14指定標(biāo)準(zhǔn)且寫代碼時(shí)避免使用過(guò)于新鮮的語(yǔ)法特性。我驗(yàn)證過(guò)一份實(shí)例庫(kù)里的代碼用-stdc17編譯和用-stdc11編譯結(jié)果的運(yùn)行效率差異明顯因?yàn)樾掳鏄?biāo)準(zhǔn)對(duì)移動(dòng)語(yǔ)義優(yōu)化得更好。對(duì)于做學(xué)習(xí)用途C11是兼容性最好的選擇。4.5 坑5構(gòu)造與析構(gòu)不配對(duì)內(nèi)存泄漏比崩潰更難抓現(xiàn)象實(shí)例ex044動(dòng)態(tài)數(shù)組類跑完100次循環(huán)后內(nèi)存占用只增不減。原因拷貝構(gòu)造函數(shù)沒(méi)有實(shí)現(xiàn)深拷貝默認(rèn)的淺拷貝導(dǎo)致兩塊內(nèi)存同時(shí)被釋放或者都沒(méi)有被釋放。解決用valgrind做內(nèi)存檢測(cè)或者直接遵守三法則析構(gòu)函數(shù)、拷貝構(gòu)造函數(shù)、拷貝賦值運(yùn)算符應(yīng)該同時(shí)提供或同時(shí)不提供。實(shí)際排查時(shí)我常駐一個(gè)簡(jiǎn)單習(xí)慣任何類里只要手動(dòng)寫了析構(gòu)函數(shù)第一步就去查有沒(méi)有配套的拷貝構(gòu)造和賦值重載。提示不要依賴程序能跑完就認(rèn)定沒(méi)有內(nèi)存問(wèn)題內(nèi)存泄漏往往是悄無(wú)聲息的系統(tǒng)不會(huì)主動(dòng)提示只有長(zhǎng)時(shí)間運(yùn)行或針對(duì)內(nèi)存做專項(xiàng)檢測(cè)才會(huì)暴露。5. 進(jìn)階用法把100個(gè)實(shí)例變成自己的代碼素材庫(kù)下完資源、跑完一遍不叫真正擁有。我的習(xí)慣是把實(shí)例庫(kù)打散重組按自己的使用場(chǎng)景重新編排索引這樣面試前、寫代碼時(shí)都能快速定位到需要的模板。5.1 按高頻考點(diǎn)重組實(shí)例面試前的三小時(shí)速查表我把100個(gè)實(shí)例拆成面試向和技術(shù)積累向面試向只保留高頻考點(diǎn)字符串反轉(zhuǎn)、鏈表反轉(zhuǎn)、二叉樹(shù)遍歷、二分查找、排序應(yīng)用、棧與隊(duì)列互相實(shí)現(xiàn)、map的底層用法。建立一個(gè)速查表列實(shí)例編號(hào)和對(duì)應(yīng)題目比如反轉(zhuǎn)鏈表對(duì)應(yīng)ex040和ex041兩個(gè)版本一個(gè)是循環(huán)寫法一個(gè)是遞歸寫法。筆試前的三小時(shí)我只刷這20個(gè)實(shí)例不看其余80個(gè)因?yàn)榭紒?lái)考去就這些變化。速查表的另一個(gè)作用是查漏補(bǔ)缺——你看到某道題沒(méi)有對(duì)應(yīng)實(shí)例時(shí)會(huì)意識(shí)到自己的盲區(qū)在哪里。5.2 給實(shí)例加一層基準(zhǔn)測(cè)試復(fù)雜度變化一眼看清這個(gè)方法適合想深入理解算法復(fù)雜度的讀者。我用std::chrono給排序?qū)嵗龑懥撕?jiǎn)單的計(jì)時(shí)包裝分別跑一萬(wàn)、十萬(wàn)、百萬(wàn)條數(shù)據(jù)的冒泡和快速排序數(shù)據(jù)量增大十倍看耗時(shí)變化復(fù)雜度概念立刻就具體了。#include chrono #include iostream #include vector // 用高精度時(shí)鐘測(cè)量函數(shù)執(zhí)行時(shí)間 template typename Func, typename Vec void measureTime(Func func, Vec data) { auto start std::chrono::high_resolution_clock::now(); func(data); auto end std::chrono::high_resolution_clock::now(); double seconds std::chrono::durationdouble(end - start).count(); std::cout 耗時(shí): seconds 秒 std::endl; }參數(shù)說(shuō)明Func是轉(zhuǎn)發(fā)引用可以傳入lambda表達(dá)式high_resolution_clock提供納秒級(jí)精度durationdouble把時(shí)間差轉(zhuǎn)成以秒為單位的浮點(diǎn)數(shù)。把同一個(gè)vector分別傳給冒泡和快排對(duì)比增長(zhǎng)率比任何教科書上的說(shuō)法都直觀。5.3 實(shí)例模板化哪些代碼值得提取哪些邊界必須保留從實(shí)例庫(kù)里提取可復(fù)用的模板時(shí)我的經(jīng)驗(yàn)是只提取結(jié)構(gòu)穩(wěn)定、變化不頻繁的部分。比如二分查找的框架、文件讀取的標(biāo)準(zhǔn)結(jié)構(gòu)、類封裝的基本骨架這些可以模板化而涉及具體業(yè)務(wù)邏輯的部分比如成績(jī)排序的規(guī)則、單詞清洗的規(guī)則必須保留成參數(shù)或接口不要注入模板。模板化的邊界在于如果你發(fā)現(xiàn)每次使用都要改模板內(nèi)部代碼那這就不算模板硬提取只會(huì)增加維護(hù)成本。我在實(shí)例庫(kù)基礎(chǔ)上沉淀了大約15個(gè)這樣的代碼骨架日常寫工具時(shí)直接復(fù)制骨架再填邏輯效率提升明顯。另外我養(yǎng)成了一個(gè)固定的復(fù)查流程每次把一個(gè)實(shí)例的代碼挪進(jìn)自己的工程時(shí)強(qiáng)制走一遍三個(gè)檢查——編譯選項(xiàng)確認(rèn)C版本、是否加了pthread、邊界條件補(bǔ)全空容器、空字符串、單個(gè)元素、釋放邏輯核對(duì)new與delete配對(duì)、資源是否在異常路徑上被釋放。這個(gè)流程救過(guò)我太多次。有個(gè)深刻的教訓(xùn)是某次把ex094的文件檢查代碼搬進(jìn)新工程跳過(guò)了一處對(duì)空文件的處理線上跑了三個(gè)小時(shí)才發(fā)現(xiàn)統(tǒng)計(jì)結(jié)果為空花在排查上的時(shí)間遠(yuǎn)超先寫保護(hù)條件的成本。從那以后我堅(jiān)持每搬一份代碼就做一遍這三個(gè)檢查不再偷懶。希望這些經(jīng)驗(yàn)?zāi)軒湍阍谟眠@份實(shí)例庫(kù)時(shí)少走一些彎路也祝你編譯一次通過(guò)、運(yùn)行沒(méi)有警告、內(nèi)存不泄漏。本文還有配套的精品資源點(diǎn)擊獲取