靜態**分析工具可簡化編碼過程,檢測出錯誤並幫助修復。pvs-studio 是乙個用於 c/c++ 的靜態**分析工具。該團隊檢測了 200 多個 c/c++ 開源專案,包括了 unreal engine、php、haiku、qt 和 linux 核心等知名專案。於是他們每天分享乙個錯誤案例,並給出相應建議。
這個 bug 是在 unreal engine 4 的源**中發現的。
錯誤**:
void fslatenotificationmanager::getwindows(
tarray< tsharedref >& outwindows) const
}解釋:
如果不讀標題的話,你可能很難發現這段**裡的問題。第一眼看上去這段**完全正確,其實它並不完美。沒錯,我指的是後自增運算子 iter++ 。 我們應該盡量使用前自增運算子而不是後自增運算子,即用 ++ iter 代替 iter++ 。 為什麼要這麼做,有什麼有實際價值?下面我會詳細解釋。
正確**:
void fslatenotificationmanager::getwindows(
tarray< tsharedrefqdurbuvmwindow> >& outwindows) const
}建議:
字首和字尾形式之間的區別是眾所周知的。我希望它們內部程式設計客棧結構的區別(告訴了我們運算法則)大家也是清楚的。如果你有使用過運算子過載的話,肯定已經意識到了。沒有用過的話,我在這兒簡單地解釋一下(用過運算子過載的可以跳過下面關於運算子過載的例子)。
前自增運算子改變了物件的狀態並返回物件改變後的狀態,不需要建立臨時物件。下面是前自增運算子的例子:
myownclass& operator++()
程式設計客棧
後自增運算子也改變了物件的狀態但是返回的是物件改變前的狀態,並且需要建立乙個臨時物件。下面是後自增運算子過載的例子:
myownclass operator++(int)
看到上面這段**,你會發現有乙個額外的操作,就是要建立乙個臨時物件,在實踐中這點太重要了!
現在的編譯器做**優化的時候非常智慧型,如果沒有用處,是不會隨便建立臨時物件的。這就是為什麼在發布版中我們很難發現i++和++i的區別。
但是在除錯模式下進行程式除錯的時候就是另一回事了,這時候你會看到效能上有很大差別。
有一些例子可以估計除錯版本中使用前自增和後自增運算子的**執行時間,我們可以看到使用字尾形式所用時間幾乎是字首的四倍。
有人會說:」那又怎麼樣?反正發布版都是一樣的。」,這種想法說對也對說不對也不對。通常我們會花更多www.cppcns.com的時間做單元測試和除錯程式,所以大多數時間都在除錯版本下工作,誰也不想浪費時間在那兒等吧?
關於「對於迭代器,我們是否應該用前自增運算子(++i)來代替後自增運算子(i++)?」這個問題,我想認真地回答: 「是的,真應該這麼做」。 你會發現在除錯版本中速度大大提公升。 如果迭代器很複雜的話,這麼做的好處更是顯而易見了。
這個錯誤是用靜態**分析工具 pvs-studio 發現的,錯誤資訊為:v803 效能下降。 如果iter是迭代器的話,使用前自增運算子會更高效,使用++iter代替iter++.
總結
C 小I選賓館 SDUT
time limit 1000 ms memory limit 65536 kib problem description 小 i 去天津玩啦,一路上,他跟他的同學發生了許多有趣的事。到了晚上了,小 i 跟他的同學們要選乙個賓館住下了。但是形形色色的賓館讓小 i 不知所措。對於乙個賓館來說,有許多特...
C 常用知識點 I
1 純虛函式 純虛函式是只有宣告沒有定義的虛函式,是對子類的約束,是介面繼承。包含純虛函式的類是抽象類,不能例項化,只有實現了純虛函式的子類才能例項化建立物件。2 typedef 和 define 區別 define是預處理命令,在預處理是執行簡單的替換,不做正確性的檢查 typedef是在編譯時處...
用java位元組碼解釋i 和 i
原址 先看4個題目 int i 0 i i int i 0 i i int i 0 int j 0 j i i int i 0 int j 0 j i i i 每道題裡的i和j都是多少?用myeclipse測試,結果分別是 i 0,i 1,i 2,j 1,i 3,j 3。i 和 i的問題,困擾很多人...