C++11 Range-based for-loop efficiency “const auto &i” versus “auto i”

后端 未结 3 1580
耶瑟儿~
耶瑟儿~ 2020-12-07 13:15

In C++11, I can iterate over some container like so:

for(auto i : vec){
   std::cout << i << std::endl;
}

But I know that this

相关标签:
3条回答
  • 2020-12-07 13:41

    Imagine if your vector contains strings. Long strings. 5000 long strings. Copy them unnecessarily and you end up with a nicely written for loop that is awfully inefficient.

    Make sure your code follows your intention. If you do not need a copy inside of the loop, do not make one.

    Use a reference & as suggested above, or iterators.

    0 讨论(0)
  • 2020-12-07 14:06

    Disclaimer: In general the difference between auto and auto& is subtle, partly a matter of style, but sometimes also a matter of correctness. I am not going to cover the general case here!

    In a range based for loop, the difference between

    for (auto element : container) {}
    

    and

    for (auto& element_ref : container) {}
    

    is that element is a copy of the elements in the container, while element_ref is a reference to the elements in the container.

    To see the difference in action, consider this example:

    #include <iostream>
    
    int main(void) {
        int a[5] = { 23,443,16,49,66 };
    
        for (auto i : a) i = 5;       
        for (const auto& i : a) std::cout << i << std::endl;
        for (auto& i : a) i = 5;   
        for (const auto& i : a) std::cout << i << std::endl;    
    }
    

    It will print

    23
    443
    16
    49
    66
    5
    5
    5
    5
    5
    

    because the first loop works on copies of the array elements, while the second actually modifies the elements in the array.

    If you dont want to modify the elements then often a const auto& is more appropriate, because it avoids copying the elements (which can be expensive).

    0 讨论(0)
  • 2020-12-07 14:07

    Yes. The same reason if you only ever read an argument you make the parameter const&.

    T        // I'm copying this
    T&       // I'm modifying this
    const T& // I'm reading this
    

    Those are your "defaults". When T is a fundamental type (built-in), though, you generally just revert to const T (no reference) for reading, because a copy is cheaper than aliasing.


    I have a program that I'm developing in which I'm considering making this change throughout, since efficiency is critical in it

    1. Don't make blind sweeping changes. A working program is better than a fast but broken program.
    2. How you iterate through your loops probably won't make much of a difference; you're looping for a reason, aren't you? The body of your loop will much more likely be the culprit.
    3. If efficiency is critical, you want to use a profiler to find which parts of your program are actually slow, rather than guess at parts that might be slow. See #2 for why your guess may be wrong.
    0 讨论(0)
提交回复
热议问题