move コンストラクタが入ったので、STLコンテナを使っているコードは、ソースコードを変えなくても速くなることがあるよ、という話。
つまり。
コンパイラオプションを -std=c++98 から -std=c++11 に変えるだけで速くなることがある。
コード
実際に 100倍以上速くなるコードは下記の通り:
c++11_or_c++98
//clang++ -O2 -std=c++11 strvec.cpp
// or
//clang++ -O2 -std=c++98 strvec.cpp
# include <vector>
# include <time.h>
# include <utility>
# include <iostream>
# include <string>
double getTick()
{
timespec t;
clock_gettime(CLOCK_REALTIME, &t);
return t.tv_sec + t.tv_nsec*1e-9;
}
int const N1 = 10000;
int const N2 = 5000;
std::vector<std::string> prepare()
{
std::vector<char> v(N1);
std::fill(v.begin(), v.end(), 'a' );
std::vector<std::string> r;
for( int i=0 ; i<N2 ; ++i ){
r.push_back(std::string(v.begin(), v.end()));
}
return r;
}
void test( char const * title )
{
std::vector<std::string> a = prepare();
double tick = -getTick();
while( 0<a.size() ){
a.erase( a.begin() );
}
tick += getTick();
std::cout << title << ": " << tick << std::endl;
}
int main()
{
# if 201103L<=__cplusplus
test("c++11");
# else
test("c++98");
# endif
return 1;
}
結果
手元のマシンでの実行結果は下表の通り:
| オプション | 出力 |
|---|---|
| -O2 -std=c++98 | c++98: 8.22603 |
| -O2 -std=c++11 | c++11: 0.0721948 |
タイトルは「100倍以上」としたけど、N1 と N2 を調整して 100倍ちょっとになるようにしたんであって、1000倍にも1万倍にもなる。
で。
冒頭に書いたとおり、moveコンストラクタが導入されているのが原因。
細かく書くと:
-
std::stringにnoexceptな moveコンストラクタがある - moveコンストラクタは、コピーコンストラクタよりもずっと速い
-
std::vectorがerase内で 要素型の moveコンストラクタを利用している
ということが原因。
C++11 はなんとなく auto・ラムダ・std::thread あたりに注目していたんだけど、ソースコードそのままで高速化する場合があるとは思っていなかった。面白い。