简体   繁体   中英

Range-based for loop and std::vector: are elements processed in order?

I am using a std::vector where the first element is somehow special, and need a slightly different handling than other elements.

I would like to use the C++11 range-based for loop for more readability, is the following code correct and good practice in this situation?

std::vector<T> v;

// [...] build v

bool isFirst = true;
for(auto element : v) 
{
    // [...] do lots of things common to all elements

    if(isFirst)
    {
        // [...] do something that only applies to the first element
    }

    // [...] do lots of things common to all elements

    isFirst = false;       
}

More technically, when using a range-based for loop with std::vector , are elements guaranteed to be processed in order, from v.front() to v.back() ?

are elements guaranteed to be processed in order

Yes.

A range-based for of the form for ( for-range-declaration : expression ) statement will be evaluated equivalently to: [stmt.ranged]/1

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

Where the range-init is (expression) (with the expression after the colon in the original range-based for statement), begin-expr essentially is begin(__range) and end-expr essentially is end(__range) .


is the following code correct and good practice in this situation?

I'll provide an alternative rather than judging (-> Code Review ):

template<class It>
struct range
{
    It beg;
    It en;
    It begin() { return beg; }
    It end() { return en; }
};

template<class It>
range<It> make_range(It beg, It en) { return {beg, en}; }

std::vector<int> v;

if(v.size() > 0)
{
    auto r = make_range(begin(v)+1, end(v));
    for(auto const& e : r)
    {
        // do.
    }
}

Yes of course they are processed in order otherwise they would have an extremely limited use. Here's another way you could do it.

std::vector<T> v;

// [...] build v

auto front = v.front();
/* do stuff to first */
for(auto iter = v.begin()+1; iter != v.end() ; ++iter) 
{
    //*iter is now the element incase you didn't know how iterators work
    // [...] do lots of things common to all elements
}  

This avoids all the checking for being first element, and doesn't add much code

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM