Range-based for loopで参照にした時としない時の速度面での違い
Range-based for loopで参照にした時としないときではどのような違いがあるでしょうか。
特に速度的な面では違いがあるのでしょうか?例えばvectorをRange-based for loopで回す場合、単に値を書き換えることなく使う場合、通常のケースでは下記のどのケースが良いのでしょうか?直感的には3だと思われるのですが、今まで常に1を使っていました。
vector<string> vec =
{
"foo", "bar", "baz"
};
// case 1
for ( auto it : vec )
{
cout << it << endl;
}
// case 2
for ( auto &it : vec )
{
cout << it << endl;
}
// case 3
for ( const auto &it : vec )
{
cout << it << endl;
}
追記 -------------
皆さま、申し訳ございません。確かに質問として成り立っておりませんでした。
私のほうでCygwin上のgcc 4.8.3でのベンチマークを追記いたします。
100万行程度では差がほとんど見られなかったので
ランダムなアルファベット文字列1000万行のテキストで最適化オプションなしで
計測いたしました。
ケース1 参照なしのパターン
#include <iostream>
#include <fstream>
#include <chrono>
#include <vector>
using namespace std;
int main()
{
vector<string> v;
ifstream ifs("test_mil.txt");
if (ifs.fail()) return -1;
for (string line; getline(ifs, line); )
{
v.push_back(line);
}
const auto startTime = chrono::system_clock::now();
string ss;
int i = 0;
for (auto s : v)
{
if (i % 2 == 0)
ss = s.substr(i % s.size());
else
ss = s;
cout << (i % 2);
i++;
}
cout << '\n';
const auto endTime = chrono::system_clock::now();
const auto timeSpan = endTime - startTime;
cout << "処理時間: "
<< chrono::duration_cast<chrono::milliseconds>(timeSpan).count()
<< " [ms]" << std::endl;
cout << ss << endl;
return 0;
}
ケース2 参照のパターン
#include <iostream>
#include <fstream>
#include <chrono>
#include <vector>
using namespace std;
int main()
{
vector<string> v;
ifstream ifs("test_mil.txt");
if (ifs.fail()) return -1;
for (string line; getline(ifs, line); )
{
v.push_back(line);
}
const auto startTime = chrono::system_clock::now();
string ss;
int i = 0;
for (auto &s : v)
{
if (i % 2 == 0)
ss = s.substr(i % s.size());
else
ss = s;
cout << (i % 2);
i++;
}
cout << '\n';
const auto endTime = chrono::system_clock::now();
const auto timeSpan = endTime - startTime;
cout << "処理時間: "
<< chrono::duration_cast<chrono::milliseconds>(timeSpan).count()
<< " [ms]" << std::endl;
cout << ss << endl;
return 0;
}
計測結果:
ケース1 3123ms 3125ms 3135ms 平均 3128ms
ケース2 2944ms 2927ms 2935ms 平均 2935ms
ということでケース2のほうが速いことがわかりました。
また次のようなコードを書くと
#include <iostream>
#include <vector>
using namespace std;
class mystring : public std::string {
public:
mystring(const char *str) : std::string(str) { }
// コピーコンストラクタ
mystring(const mystring &rhs) : string(rhs.c_str())
{
cout << "mystring copy constructor" << endl;
}
};
int main()
{
vector<mystring> v;
mystring m("abc");
v.push_back(m);
cout << "test start" << endl;
for (auto &s : v)
{
cout << s << endl;
}
cout << "test end" << endl;
return 0;
}
このケースではコピーコンストラクタが呼び出されず、
for (auto s : v)としたほうではコピーコンストラクタが呼び出されました。
よって私の環境下につきましてはjoy1192さんの解答の通りとなりました。