MISRA C++:2023?,MISRAC++標(biāo)準(zhǔn)的下一個(gè)版本,就在這里!為了幫助您了解MISRA C++:2023與上一版本之間的變化,我們繼續(xù)Perforce首席技術(shù)支持工程師Frank van den Beuken博士撰寫(xiě)的第三期博客系列。
在前兩篇博客中,我們向您介紹了新的 MISRA C++ 標(biāo)準(zhǔn)和C++ 的歷史。在這篇博客中,我們將仔細(xì)研究以 C++ 中for循環(huán)為中心的特定規(guī)則。
什么是 MISRA C++:2023Rule9.5.2,為什么它很重要?
MISRA C++:2023引入了規(guī)則9.5.2,“ for范圍初始值設(shè)定項(xiàng) 最多應(yīng)包含一個(gè)函數(shù)調(diào)用”,以避免在基于范圍的for語(yǔ)句的for范圍初始值設(shè)定項(xiàng)創(chuàng)建臨時(shí)對(duì)象時(shí)可能發(fā)生的未定義行為。
為了理解為什么會(huì)發(fā)生這種情況,讓我們仔細(xì)看看基于 C++ 范圍的for循環(huán)。
什么是 C++ 中基于范圍的for循環(huán)?
在編程中,循環(huán)用于重復(fù)代碼塊。當(dāng)您知道要在代碼塊中循環(huán)多少次時(shí),請(qǐng)使用for循環(huán)。
C++ 基于范圍的for循環(huán)是在C++11中引入的,作為容器迭代的簡(jiǎn)潔表示法。
傳統(tǒng)循環(huán)源自 C 語(yǔ)言,具有可選的循環(huán)初始化,然后是循環(huán)條件,最后是循環(huán)增量表達(dá)式。
傳統(tǒng)for循環(huán)可用于迭代容器,如下所示:
std::vector v = { "Example", "vector", "of", "strings" }; for ( auto &&i = v.begin(); i != v.end(); ++i ) { std::cout << *i << “ “;? } std::cout << std::endl;? |
使用基于范圍的for時(shí),迭代器的使用是隱式的:
for ( auto &&s: v ) { std::cout << s << “ “;? } |
對(duì)于同一循環(huán),這是一個(gè)更簡(jiǎn)單的表示法。C++ 語(yǔ)言標(biāo)準(zhǔn)指出它是以下方面的縮寫(xiě):
{ auto && __range = v; auto __begin = __range; auto __end = v.end(); for (; __begin != __end; ++__begin) { auto &&s = *__begin; std::cout << s << “ “;? } } |
但是,這種表示法存在一定的局限性。在上面的示例中, __range 是用v初始化的,這是一個(gè)更簡(jiǎn)單的變量,但也可以使用一個(gè)復(fù)雜的表達(dá)式,為其創(chuàng)建多個(gè)臨時(shí)對(duì)象。
讓我們考慮使用一個(gè)函數(shù),該函數(shù)返回字符串的向量,并具有:
- 一個(gè)輸出用空格分隔的字符串的循環(huán),如上所述
- 第二個(gè)循環(huán),打印第一個(gè)字符串的字母,用空格分隔:
std::vector createStrings() { return { "Example”, "vector", "of", "strings" }; } int main() { for ( auto w: createStrings() ) { std::cout << w << " "; }? std::cout << std::endl;? for ( auto c: createStrings()[0] ) { std::cout << c << " "; }? std::cout << std::endl;? } |
如果我們執(zhí)行此操作,第一個(gè)循環(huán)將按預(yù)期運(yùn)行,但第二個(gè)循環(huán)將調(diào)用未定義的行為。 問(wèn)題是 createStrings()[0]有兩個(gè)函數(shù)調(diào)用。最里面的調(diào)用是createStrings的調(diào)用 ,最外面的調(diào)用是對(duì)索引運(yùn)算符[]的調(diào)用。
未定義行為的原因是 “ createStrings ”返回的臨時(shí)對(duì)象 用作“ operator[ ]”調(diào)用的參數(shù),因此,根據(jù)C++的規(guī)則,臨時(shí)對(duì)象的生存期不會(huì)延長(zhǎng)。
返回頁(yè)首
MISRA C++:2023Rule9.5.2 如何防范未定義的行為
MISRA C++:2023Rule9.5.2 旨在防止這種情況。MISRA C++:2023引入了規(guī)則9.5.2,該規(guī)則 要求for范圍初始值設(shè)定項(xiàng)最多應(yīng)包含一個(gè)函數(shù)調(diào)用。
它還建議通過(guò)在循環(huán)范圍之前的單獨(dú)聲明中執(zhí)行內(nèi)部函數(shù)調(diào)用來(lái)解決此問(wèn)題。例如:
auto strings = createStrings(); for ( auto c: strings[0] ) { std::cout << c << " "; }? |
現(xiàn)在,初始值設(shè)定項(xiàng)中只有一個(gè)函數(shù)調(diào)用,因此生存期擴(kuò)展具有所需的效果,并且行為已完全定義。
請(qǐng)注意,此問(wèn)題已在 C++23 中得到解決,其中初始值設(shè)定項(xiàng)的所有臨時(shí)項(xiàng)的生存期已擴(kuò)展到整個(gè)for語(yǔ)句。
使用 Helix QAC 執(zhí)行MISRA C++:2023規(guī)則
Perforce 的Helix QAC是一種靜態(tài)分析工具,在提供 MISRA C 和MISRA C++合規(guī)性檢查以及許多其他有價(jià)值的分析功能方面處于領(lǐng)先地位。
Helix QAC 通過(guò)其標(biāo)準(zhǔn)合規(guī)性模塊為MISRA C++:2023規(guī)則提供100%的強(qiáng)制執(zhí)行覆蓋率,現(xiàn)已推出。靜態(tài)分析工具查找并報(bào)告C和C++中違反MISRA規(guī)則和指令的情況。
歡迎聯(lián)系北匯信息,申請(qǐng)Helix QAC試用。
-
C語(yǔ)言
+關(guān)注
關(guān)注
180文章
7594瀏覽量
135849 -
代碼
+關(guān)注
關(guān)注
30文章
4722瀏覽量
68229 -
MISRA
+關(guān)注
關(guān)注
0文章
21瀏覽量
6956
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論