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