4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

for( size_t i=0, n=v.size(); i<n; ++i) が速いかどうか

Last updated at Posted at 2022-01-05

これは何?

を見て、どんだけ違うの? と思って試してみた。

簡単なケース

n で受ける

c++
std::size_t sum1( std::vector<size_t> const & v ){
    std::size_t sum=0;
    for( std::size_t i=0, n=v.size(); i<n; ++i){
        sum += i*v[i];
    }
    return sum;
}

毎回 .size() を呼ぶ

c++
std::size_t sum2( std::vector<size_t> const & v ){
    std::size_t sum=0;
    for( std::size_t i=0; i<v.size(); ++i){
        sum += i*v[i];
    }
    return sum;
}

比較してみた

これを、以下のコンパイラで -O2 でアセンブラを作って比較した。環境は macOS (intel)。

  • Apple clang version 13.0.0 (clang-1300.0.29.30) / Target: x86_64-apple-darwin21.2.0
  • g++-11 (Homebrew GCC 11.2.0) 11.2.0

結果は変わらず。
コンパイラは、ループ回数が変わらないことぐらいお見通し。

引数についてる const を外しても同じ。

もっと面倒な例

ループ内で vector を別の関数に const 参照で渡すんだけど、関数の実装は不明という場合。

n で受ける

c++
int foo( std::size_t x, std::vector<size_t> const & v );

int sum3( std::vector<size_t> & v ){
    int sum=0;
    for( std::size_t i=0, n=v.size(); i<n; ++i){
        sum += foo(i,v);
    }
    return sum;
}

毎回 .size() を呼ぶ

c++
int foo( std::size_t x, std::vector<size_t> const & v );

int sum4( std::vector<size_t> & v ){
    int sum=0;
    for( std::size_t i=0; i<v.size(); ++i){
        sum += foo(i,v);
    }
    return sum;
}

比較してみた

先ほどと同じ環境で比較してみたら、両方とも差があった。
std::vector<size_t> const & で要求している関数に渡してるんだから v.size() は変わらないということになりそうだけど、コンパイラは const 修飾子を信用してないらしい。

まとめ

簡単な例しか調べてないけど、ループ内で vector を他の関数に渡したりしてなければ、コンパイラは要素数が変わらないことに気づくんじゃないかな。

一方。別の関数に vector の参照を渡すと、それが const 参照でもコンパイラは疑心暗鬼になって毎回 .size() を呼ぶ。

まあ呼ぶっていっても関数呼び出しコードは作られなくて、メモリを参照するだけだけどね。

4
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?