代碼審查又被懟了?學會這三個 C++17 屬性立刻提升代碼質量
小王最近剛入職一家互聯網公司,今天又是元氣滿滿的一天 ??
"老張,救命啊!" 小王沖進辦公室,手里還拿著自己的保溫杯。
老張正在喝著他標志性的枸杞泡茶 ??,抬頭看了看慌張的小王:"怎么了?又遇到什么難題了?"
"我們的代碼審查工具一直報警,說什么 switch 語句有 fall through 問題。我看了半天文檔也沒看明白..." 小王撓著頭發,一臉困惑 ??
老張放下保溫杯,露出了高深莫測的微笑:"哦?這個問題啊,來來來,我給你講個故事..."
從一個 bug 說起
"先看這段代碼:"
switch (value) {
case 1:
doSomething();
// 警告:這里有個隱藏的陷阱!
case 2:
doSomethingElse();
break;
}
"誒?這代碼有什么問題嗎?" 小王湊近屏幕 ??
"你還記得上周那個用戶投訴的 bug 嗎?" 老張喝了口枸杞茶。
小王一拍腦門:"對對對!就是那個訂單狀態莫名其妙變化的問題!"
"沒錯,就是這種 switch 語句惹的禍。" 老張放下茶杯,"你看,如果 value 是 1,程序不僅會執行 case 1 的代碼,還會繼續往下執行 case 2 的代碼..."
"啊!" 小王恍然大悟,"原來是忘記寫 break 了!" ??
C++17 的救星
老張點點頭:"但有時候,我們確實需要這種特性。C++17 給我們提供了一個優雅的解決方案:"
switch (value) {
case 1:
doSomething();
[[fallthrough]]; // 告訴編譯器:這是故意的!
case 2:
doSomethingElse();
break;
}
"這...這簡直太棒了!" 小王興奮地說,"等等,我記得還看到過其他類似的標記..." ??
別讓返回值白白浪費:[[nodiscard]] 屬性
"說到這個..." 老張神秘地笑了笑,從抽屜里掏出一個小本本 ??,"你知道為什么我總能快速定位問題嗎?"
小王搖搖頭,一臉好奇 ??
"因為我把踩過的坑都記在這里了!來看看這個例子:"
int calculateDiscount() {
// 計算折扣金額
return discount;
}
void processOrder() {
calculateDiscount(); // 警告:返回值被忽略了!
applyTax();
}
"這段代碼有什么問題?" 老張問道。
小王仔細看了看:"嗯...計算了折扣但是沒用上?"
"沒錯!" 老張贊許地點點頭,"這種bug特別隱蔽。有時候我們寫完代碼就忘記用返回值了。C++17 給了我們一個法寶:"
[[nodiscard]] int calculateDiscount() {
return discount;
}
"哇!這樣如果忘記使用返回值,編譯器就會報警告?" 小王眼睛一亮 ?
"聰明!" 老張喝了口枸杞茶,"不過還有個有趣的情況..."
暫時不用也不報警:[[maybe_unused]] 屬性
正說著,產品經理小李急匆匆地跑了進來 ??♂?
"老張!那個新功能暫時不上了,代碼先留著!"
"說曹操,曹操就到。" 老張笑著對小王說,"這種情況我們就需要第三個屬性了:"
[[maybe_unused]] void newFeature() {
// 暫時用不上的新功能
}
void legacyFunction([[maybe_unused]] int oldParam) {
// 參數暫時不用,但后面可能會用
}
"這樣編譯器就不會對未使用的函數和參數發出警告了!" 小王恍然大悟 ??
"沒錯!" 老張滿意地說,"這三個屬性看似簡單,但都是實戰中的法寶啊!"
"[[fallthrough]] 防止 switch 穿透事故..." "[[nodiscard]] 提醒我們別忘了返回值..." "[[maybe_unused]] 處理暫時用不上的代碼..."
小王掰著手指數著,臉上露出了開心的笑容 ??
"學會了這三個屬性,以后代碼審查就不用擔心了!" 老張拍拍小王的肩膀。
"謝謝老張!" 小王站起身來,"我這就去優化代碼!"
看著小王歡快離去的背影,老張又給自己的枸杞茶續上了熱水 ??
小結
C++17 新增的三個屬性各有妙用:
- [[fallthrough]] 用于表示 switch 語句中刻意的 case 穿透
- [[nodiscard]] 提醒調用者不要忽略函數返回值
- [[maybe_unused]] 標記暫時不用但后面可能會用到的代碼
這些小工具不僅能幫助我們寫出更清晰的代碼,還能預防一些常見的bug。正如老張所說,編程就像泡茶,看似簡單,但其中大有學問啊!