2016-11-10 75 views
2
#include <vector> 
#include <iostream> 

class Range { 
    typedef typename std::vector<int> Vec; 
    typedef typename Vec::iterator Iterator; 
public: 
    Range(Vec& vec, const int start_id, const int size) 
      : vec_{vec}, 
       it_begin_{vec_.begin() + start_id}, 
       it_end_ {vec_.begin() + start_id + size} 
    {} 
    Iterator& begin() {return it_begin_;} 
    Iterator& end() {return it_end_;} 
private: 
    Vec& vec_; 
    Iterator it_begin_; 
    Iterator it_end_; 
}; 

int main() 
{ 
    std::vector<int> a; 
    a.resize(100); 
    Range range(a,0,10); 
    for (auto it = range.begin(); it != range.end(); ++it) { // Line A 
     std::cout << it - range.begin() << "\n"; // Line B 
    } 
} 

Assembly hereIterator會多次循環調用end()嗎?

假設我用的優化(如g++ -Ofast)。

在A行中,程序會多次調用range.end(),而不是保存range.end()的值,並在循環的每次迭代中將其與該值進行比較?

在B行中,程序會多次調用range.begin(),而不是保存整個循環的range.begin()的值,然後在循環的每次迭代中從該值中減去該值?

+2

爲什麼不編譯和檢查程序集? – NathanOliver

+0

呃。我想每個人都會知道......(除非我不知道)。 –

回答

3

在您的代碼中,優化器可以看到begin()end()的實現。它可以內聯它們,並將不變量從循環中提取出來。

如果begin()end()main()位於不同的翻譯單元中,答案可能會不同,因爲鏈接時間對於此類優化通常來說太晚了。

1

.end()成員的訪問具有不變的複雜度,它被讀取一次,並被用作循環中的限制。您可以查看容器的this示例,但它也適用於其他人。

3

很難預測優化器在給定優化級別上會做什麼和不會做什麼。雖然這種特殊的轉換是微不足道的,並且通常在允許內聯時完成,但不能保證。

如果有疑問,我會遵循古老的俄語說法,大致翻譯爲'對優化器有信心,但不要自己虛擬!'。所以我會使用一個const變量來存儲調用的結果。它首先會使代碼更具可讀性,並且作爲一個很好的副作用,它可能會幫助一些似是而非的優化器。一個好的優化器會消除變量。

+0

在這裏,我想我們稱之爲「信任,但要確認」。 – user4581301