簡體   English   中英

如果沒有if,std :: count_if會更快嗎?

[英]Would std::count_if be faster without an if?

這是gcc std::count_if代碼

template<typename _InputIterator, typename _Predicate>
  typename iterator_traits<_InputIterator>::difference_type
  count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred)
 {
  [snip]
  typename iterator_traits<_InputIterator>::difference_type __n = 0;
  for (; __first != __last; ++__first)
    if (__pred(*__first))
      ++__n;
  return __n;
}

我的問題:使用它會更好(即更快)

__n += __pred(*__first); // instead of the if statement

此版本始終執行添加,但不執行分支。

您提供的替換等同,因為對謂詞的限制遠遠少於您的想法:

  • 可以在條件上下文中使用的任何內容(可以在上下文中轉換為bool )是謂詞的有效返回類型( explicit轉換為bool就足夠了)。
  • 返回類型可以很有趣地添加到迭代器差異類型。

25算法庫[algorithms]

25.1一般[algorithms.general]

8 Predicate參數用於每當算法期望的功能對象(20.9),當施加到解引用相應的迭代的結果,返回可測試作為值true 換句話說,如果算法將Predicate pred作為其參數並first作為其迭代器參數,則它應該在構造pred(*first)上下文中正確轉換為bool (第4條) 函數對象pred不應通過解引用的迭代器應用任何非常量函數。

給予替代消化不良的最可能的回報是標准整數類型,並且值既不是0也不是1。

另外,請記住編譯器現在實際上可以真正優化(特別是C ++需要,所有模板 - 東西分層深)。

所以,首先,您建議的代碼是不同的。 那么讓我們看看兩個等價的代碼:

template<typename _InputIterator, typename _Predicate>
typename iterator_traits<_InputIterator>::difference_type
count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) {
    typename iterator_traits<_InputIterator>::difference_type __n = 0;
    for (; __first != __last; ++__first)
        if (__pred(*__first))
            ++__n;
    return __n;
}

和:

template<typename _InputIterator, typename _Predicate>
typename iterator_traits<_InputIterator>::difference_type
count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) {
    typename iterator_traits<_InputIterator>::difference_type __n = 0;
    for (; __first != __last; ++__first)
        __n += (bool) __pred(*__first);
    return __n;
}

然后,我們可以使用編譯器編譯它並查看程序集。 在我嘗試過的一個編譯器(os x on clax)下,這些編譯器產生了相同的代碼

也許你的編譯器也會產生相同的代碼,或者它可能產生不同的代碼。

從技術上講,它會,但請記住,所有大於0值都會評估為true 因此被調用的函數可能會返回一個不是1的值,這會使結果產生偏差。 此外,編譯器還具有將分支優化為條件移動的方法。

為了擴展,有一些方法可以在代碼中優化分支,但這會降低可讀性和可維護性,以及通過例如調試代碼的能力。 把斷點放下來,並且獲得很少,因為編譯器非常善於自己優化這些東西。

由編譯器生成的代碼不必在字面上機器代碼重現C ++語言構造。 僅僅因為您的C ++代碼中包含if語句並不意味着機器代碼將基於分支指令。 現代編譯器不需要也不要在生成的機器代碼中實現抽象C ++機器的行為。

因此,不可能說它是否會更快。 C ++代碼沒有任何與之相關的固有“速度”。 C ++代碼永遠不會直接執行。 從抽象的角度來看,它不能“更快”或“更慢”。 如果要通過查看代碼來分析代碼的性能,則必須查看編譯器生成的機器代碼,而不是C ++代碼。 但是更好的方法是嘗試兩種變體並通過在各種典型輸入數據上實際運行它們來對它們進行分析。

智能編譯器很可能會為您的兩個變體生成相同的代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM