2016-11-10 2 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

erh。私は誰もがそれを知っていると思った...(私はしない限り)。 –

答えて

3

コードでは、オプティマイザはbegin()end()の実装を見ることができます。それらをインライン化して、インバリアントをループから取り除くことができます。

begin()end()main()とは異なる翻訳単位である場合、そのような最適化では通常リンク時間が遅すぎるため、答えが異なる可能性があります。

1

.end()メンバーのアクセスは一定の複雑さを持っています。これは一度読み込まれ、ループの制限として使用されます。 mapコンテナのthisの例を確認できますが、他のコンテナにも適用されます。

3

特定の最適化レベルでオプティマイザが何をしているのか、またできないのかを予測するのは難しいです。この特定の変換は簡単ではなく、通常はインライン展開が許可されるたびに行われますが、それは保証されません。

疑問があるときは、古いロシア語の言葉に従うと、「オプティマイザを信じていますが、自分自身がダミーにならないようにしてください!だから私はコールの結果を格納するconst変数を使用します。まず第一に、コードをより読みやすくし、素晴らしい副作用としていくつかの逆説的なオプティマイザを助けるかもしれません。そして、良いオプティマイザは、変数をとにかく排除します。

+0

ここで私はそれを「信頼しますが、確認してください」と呼ぶと思います。 – user4581301

関連する問題