看板 C_and_CPP 關於我們 聯絡資訊
※ 引述《henry8168 (番薯猴)》之銘言: : 正在工作,在修前人的 code。 : 假設現在有 function F 和 function G, : function F 內執行的程式碼會呼叫 function G 並將某個指標作為參數傳入 G : 想請問一下高手大大們,空指標的檢查一般都在: : 1) function F 要傳入該指標到 function G 前 : 2) 收到該指標的 function G 的開頭 : 3) 1、2 兩者皆要 : 的哪個時機檢查最好? : 又有什麼優缺點? : 因為選方案 1 的話,要是某些時候呼叫 G 前忘記檢查就會出事,而且程式碼滿冗贅的; : 可是如果用方案 2 的話,在某些情況下, : 會呼叫 G 的 function F 可能已經存取過該指標,等於先保證不會為空, : 那 2 的作法就等於每次都多一道檢查行為。 : 方案 3 沒看過,可能老鳥跟菜鳥沒串好 @@? : 那有約定成俗的 coding rule 嗎? : 一般都怎麼寫比較好? 這個問題因為沒有完整情境所以回答起來會複雜些, 涉及的觀念包 含軟體驗證還有測試, 不過因為這裡是語言專版所以小弟儘量把解 說侷限在語言層面上. 首先在將指標做為函式參數時, 你需要先回 答幾個問題: 1. 是否允許呼叫端 (caller) 選擇性提供引數? 2. 如果不該是選擇性提供引數, 那應該由誰來確保它的値並 非 nullptr? 3. nullptr 應該當成合法輸入, 還是當成錯誤處理? 第一個問題完全可以用語法來描述, 譬如使用參考 (reference) 來 表示 caller 必須提供該引數, 而其他情況則是用指標. 剩下的問題如果你非得用指標不可, 那該誰來檢查指標是否為 nullptr 呢? 答案是 caller 和被呼叫端 (callee) 有可能都要檢 , 只不過檢查的方式取決於你想表達的語意, 可粗略分為以下 3 種: 1. caller 要確保指標非 nullptr 這時候參數非 nullptr 即是呼叫函式的前置條件 (pre- condition), nullptr 在這個情況被當成不合法的輸入, 但是 callee 不用對這個非法輸入做特別處理, 程式當掉 時會是 caller 的責任. 通常前置條件在 callee 會用斷 言 (assertion) 來宣告, 或是另外寫文件來描述. 你 以把斷言看做是檢查的一種, 但是 caller 在呼叫前對應 的檢查還是免不了. 標準函式庫的 strlen() 就是其中一 個例子. 2. callee 要確保指標非 nullptr nullptr 在這個情況被當成合法的輸入, 但是給了 nullptr 會有特別的行為, 可能不做事, 回傳錯誤代碼 (代碼是用來 說明為什麼 callee 無法履行義務), 或是代表操作結束. 通常 callee 會用 if 來做處理, 標準函式庫的 strtok() 是其中一個例子. caller 在遇到函式有特別行為時, 也許需 要反過來檢查是否因為引數給 nullptr 造成這個差異. 3. caller 和 callee 都不需要做 nullptr 檢查 nullptr 在這個情況被當成合法的輸入, 但如果是合法輸入 , 我們又應該如何去使用它呢? 答案是: 不需要. 通常不需 要檢查的情況會發生在參數間有相依性存在的時候, 例如我 們想印出整數陣列裡的所有元素値, 可以用下面的 print() 函式, 引數組合完全合理: void print(const int* array, size_t size) { for (size_t idx = 0; idx < size; ++idx) { std::cout << array[idx] << " "; } std::cout << std::endl; } print(nullptr, 0); // do nothing -- P1389R0: Guidelines for Teaching C++ to Beginners https://bit.ly/2GvDWKb SG20 Education and Recommended Videos for Teaching C++ https://www.cjdb.com.au/sg20-and-videos -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 123.193.76.216 (臺灣) ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1568839427.A.470.html ※ 編輯: poyenc (123.193.76.216 臺灣), 09/19/2019 04:51:16
nickchen1202: 想問一下那個print函數如果第二個參數非0會怎麼樣 09/19 07:32
Lipraxde: 那第一個參數就不該傳 nullptr 吧? 09/19 08:17
henry8168: 謝謝 我想我會傾向callee自行處理nullptr的選項 09/19 16:38