本篇介紹幾個細瑣的小特性,可以使代碼更加安全可靠。
最常見的情況是采取 for loop 遍歷某個容器,比如:
std::vectorv(10); std::iota(v,0); for(inti=v.size()-1;i>=0;--i){ std::cout< 乍看之下,似乎并無問題,但實際上卻存在安全隱患,若是 v.size() 的結果大于 std::numeric_limits
::max(),將產生 UB。 倘若你使用了類型推導,問題會更加明顯。
for(autoi=v.size()-1;i>=0;--i){ std::cout<這會輸出超出預期的結果!i 被推導為 unsigned 整型,i >= 0 將永遠為真。
這種隱患來自于類型的隱式轉換,一般編譯器只會給出警告。最簡單的解決之法就是保證整型符號的一致性,例如:
for(size_ti=v.size()-1;i結束條件也隨之變為檢測數據范圍,以避免條件在邏輯上的無效性。但如此一來,可讀性直線降低,C++20 引入了幾個與此相關的小特性,可以更安全地解決該問題。
第一個是一系列整型比較函數,它們可以安全地對不同符號的類型進行比較。如:
-1>0u;//true std::cmp_greater(-1,0u);//false因此,可以用來安全地比較不同符號的整型。
for(inti=0;std::cmp_less(i,v.size());++i){ std::cout<通過使用這些安全的比較函數,代碼隱患隨之消除。只是無法逆序遍歷了,逆序時將 size_t 賦值到 int 依舊有可能產生 UB。
此種情境,更好的方式是采用 std::ssize(),它是一個有符號的 size() 輔助函數,表意更加直接。代碼更改為:
for(inti=ssize(v)-1;i>=0;--i){ std::cout<得益于 ADL,std::ssize() 可以簡寫為 ssize()。
當然,以上只是示例需要,對于數據遍歷,Range-based for loop 是更好的方式,這樣能夠避免很多易被忽視的錯誤。
for(constauto&elem:v){ std::cout<通過 C++20 Views,還可以在遍歷時組合其他操作,如:
for(constauto&elem:v|std::reverse){ std::cout<
這是可讀性最強的方式。
當然,還有許多其他方法,比如迭代器、算法和一些技巧,但在范式上來說,那些方法很難比這里展示的方式更加簡潔,就使用來說,記住這里提到的便已足夠。
推薦閱讀點擊標題可跳轉
1、深入淺出 C++ 類型擦除
2、性能大殺器:c++中的copy elision
3、Configuring Transitive Dependencies with Modern CMake
-
函數
+關注
關注
3文章
4327瀏覽量
62569 -
C++
+關注
關注
22文章
2108瀏覽量
73618
發布評論請先 登錄
相關推薦
評論