will range based for loop in c++ preserve the index order

后端 未结 3 1442
别那么骄傲
别那么骄傲 2020-12-30 23:58

in c++11, if I use a range based for loop on vector, will it guarantee the iterating order? say, will the following code blocks are guaranteed for same output?



        
相关标签:
3条回答
  • 2020-12-31 00:47

    Yes and no (It depends on the container in use):

    • The range based for is a loop like for(iterator pos = range.begin(); pos != range.end(); ++pos) { /* with a range variable = *pos */ ... }
    • An operator [] might do something different (eg. a std::map operator does a lookup on the key and create a new entry, if the key does not exist)

    Example:

    #include <iostream>
    #include <map>
    
    int main()
    {
        typedef std::map<int, int> map;
        map m = { { 0, 0 }, { 2, 2 }, { 4, 4 } };
        for(const auto& e : m) {
            std::cout << e.first << " ";
        }
        std::cout << std::endl;
        for(map::size_type i = 0; i < m.size(); ++i) {
            std::cout << m[i] << " ";
        }
        std::cout << std::endl;
        return 0;
    }
    

    The result is:

    0 2 4 
    0 0 2 0 4 
    

    (The second result might be a good shot in the own foot or even intended)

    0 讨论(0)
  • 2020-12-31 00:48

    Yes, they are equivalent. The standard guarantees in 6.5.4:

    For a range-based for statement of the form

    for ( for-range-declaration : expression ) statement

    let range-init be equivalent to the expression surrounded by parentheses ( expression )

    and for a range-based for statement of the form

    for ( for-range-declaration : braced-init-list ) statement

    let range-init be equivalent to the braced-init-list. In each case, a range-based for statement is equivalent to

    {
      auto && __range = range-init;
      for ( auto __begin = begin-expr,
          __end = end-expr;
          __begin != __end;
          ++__begin ) {
        for-range-declaration = *__begin;
        statement
      }
    }
    

    where __range, __begin, and __end are variables defined for exposition only, and _RangeT is the type of the expression, and begin-expr and end-expr are determined as follows:

    — if _RangeT is an array type, begin-expr and end-expr are __range and __range + __bound, respectively, where __bound is the array bound. If _RangeT is an array of unknown size or an array of incomplete type, the program is ill-formed;

    — if _RangeT is a class type, the unqualified-ids begin and end are looked up in the scope of class _RangeT as if by class member access lookup (3.4.5), and if either (or both) finds at least one declaration, begin-expr and end-expr are __range.begin() and __range.end(), respectively;

    — otherwise, begin-expr and end-expr are begin(__range) and end(__range), respectively, where begin and end are looked up with argument-dependent lookup (3.4.2). For the purposes of this name lookup, namespace std is an associated namespace.

    Though your question about map is a bit nonsensical. If it's an ordered map and you iterate through the map properly, then they're equivalent. If it's an unordered map then your question doesn't really make much sense.

    0 讨论(0)
  • 2020-12-31 00:55

    Yes the two codes are guaranteed to do the same. Though I don't have a link to the standard you can have a look here. I quote: You can read that as "for all x in v" going through starting with v.begin() and iterating to v.end().

    0 讨论(0)
提交回复
热议问题