Vector back() メソッドが反復子の観点から実装されているのはなぜですか
reference back()
{ // return last element of mutable sequence
return (*(end() - 1));
}
のようなものではなく...
return (*(_Myfirst + size()));
この質問の背景:
私は最近、一部のレガシー コード (アロケータの実装) の最適化に取り組んでおり、かなりの時間が に費やされていることに気付きましたstd::vector::back()
。したがって、さまざまなコレクション(Vector vs List vs Deque)を使用していくつかの実験を行いback()
ましたが、基本的にはコレクション内の最後の要素を取得しているためvector::back()
、vector[size()-1]
これは私がテストに使用したコードです:
#include <vector>
#include <list>
#include <deque>
#include <algorithm>
#include <boost/timer/timer.hpp>
int RandomNumber () { return (rand()%100); }
void doVector( std::vector<int>& test_vec )
{
std::cout << "vect back() = " << test_vec.back() << std::endl;
{
boost::timer::auto_cpu_timer t;
for (int i = 0; i < 100000000; i++ )
test_vec.back();
}
}
void doVector2( std::vector<int>& test_vec )
{
std::cout << "vect [size()-1] = " << test_vec[test_vec.size()-1] << std::endl;
{
boost::timer::auto_cpu_timer t;
for (int i = 0; i < 100000000; i++ )
test_vec[test_vec.size()-1];
}
}
void doList( std::vector<int>& test_vec )
{
std::list<int> test_list(test_vec.begin(),test_vec.end());
std::cout << "list back() = " << test_list.back() << std::endl;
{
boost::timer::auto_cpu_timer t;
for (int i = 0; i < 100000000; i++ )
test_list.back();
}
}
void doDeque( std::vector<int>& test_vec )
{
std::deque<int> test_deq(test_vec.begin(),test_vec.end());
std::cout << "Deque back() = " << test_deq.back() << std::endl;
{
boost::timer::auto_cpu_timer t;
for (int i = 0; i < 100000000; i++ )
test_deq.back();
}
}
int _tmain(int argc, _TCHAR* argv[])
{
std::vector<int> test_vec(100);
std::generate(test_vec.begin(), test_vec.end(), RandomNumber );
doVector(test_vec);
doVector2(test_vec);
doList(test_vec);
doDeque(test_vec);
}
結果は次のとおりです。
デバッグをオンにして、リリース時間の最適化を秒単位でオフにしたため、結果を削除しました。
明らかに、vect[ size() - 1] を使用することで大幅に利益が得られます。さらに、front() よりも vect[0] を使用することで利益も得られます。私は自分自身をベクトルに縛り付けていることを認識していますが、短期的にはそれが私の選択した方向です (クイックウィン)。しかし、それは私に考えさせられました - なぜ front() と back() のベクトル実装は内部で非効率的な実装を使用するのですか?
vect back() = 41 0.183862 秒の壁、0.171601 秒のユーザー + 0.000000 秒のシステム = 0.171601 秒の CPU (93.3%)
vect [size()-1] = 41 0.416969 秒の壁、0.421203 秒のユーザー + 0.000000 秒のシステム = 0.421203 秒の CPU (101.0%)
list back() = 41 0.079119 秒の壁、0.078001 秒のユーザー + 0.000000 秒のシステム = 0.078001 秒の CPU (98.6%)
Deque back() = 41 0.186574 秒の壁、0.187201 秒のユーザー + 0.000000 秒のシステム = 0.187201 秒の CPU (100.3%)
明らかに、分析を行ったときに間違った結果を見ていました。これは、実装の選択を完全に裏付けているためです。この編集の前にこれを見た人には申し訳ありません.....