Range-based for loopで参照にした時としない時の速度面での違い


Range-based for loopで参照にした時としないときではどのような違いがあるでしょうか。  
特に速度的な面では違いがあるのでしょうか？例えばvectorをRange-based for
loopで回す場合、単に値を書き換えることなく使う場合、通常のケースでは下記のどのケースが良いのでしょうか？直感的には3だと思われるのですが、今まで常に1を使っていました。

[code]

    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;
    }
    
[/code]

追記 -------------  
皆さま、申し訳ございません。確かに質問として成り立っておりませんでした。  
私のほうでCygwin上のgcc 4.8.3でのベンチマークを追記いたします。  
100万行程度では差がほとんど見られなかったので  
ランダムなアルファベット文字列1000万行のテキストで最適化オプションなしで  
計測いたしました。

ケース1 参照なしのパターン

[code]

    #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;
    }
    
[/code]

ケース2 参照のパターン

[code]

    #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;
    }
    
[/code]

計測結果：  
ケース1 3123ms 3125ms 3135ms 平均 3128ms  
ケース2 2944ms 2927ms 2935ms 平均 2935ms  
ということでケース2のほうが速いことがわかりました。  
また次のようなコードを書くと

[code]

    #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;
    }
    
[/code]

このケースではコピーコンストラクタが呼び出されず、  
for (auto s : v)としたほうではコピーコンストラクタが呼び出されました。  
よって私の環境下につきましてはjoy1192さんの解答の通りとなりました。




case 2,case 3は用途によって使い分けるべきですが、一般的な使い方の上ではcase 1は遅くなります。

case 1の場合、  
`vector<T>`の要素を1つ1つ`auto
it`にコピーしていきます。つまり、毎回コピーコンストラクタが呼び出されるため、単純なアクセス用途であれば無駄なコストが発生します。  
`for`ループ内でコピーした値に対して破壊的な操作を行いたい場合に使用するケースは有るでしょう。

case 2, case 3の場合、  
`vector<T>`内の要素に対する参照を渡しているだけなので、高速です。  
原理的にはポインタのコピー程度のコストしか発生しません。constの有無は速度には大きく関係しないはずです。




case 2,case 3は用途によって使い分けるべきですが、一般的な使い方の上ではcase 1は遅くなります。

case 1の場合、  
`vector<T>`の要素を1つ1つ`auto
it`にコピーしていきます。つまり、毎回コピーコンストラクタが呼び出されるため、単純なアクセス用途であれば無駄なコストが発生します。  
`for`ループ内でコピーした値に対して破壊的な操作を行いたい場合に使用するケースは有るでしょう。

case 2, case 3の場合、  
`vector<T>`内の要素に対する参照を渡しているだけなので、高速です。  
原理的にはポインタのコピー程度のコストしか発生しません。constの有無は速度には大きく関係しないはずです。

