What's the best way to do a backwards loop in C/C#/C++?

后端 未结 14 2701
终归单人心
终归单人心 2020-11-28 01:39

I need to move backwards through an array, so I have code like this:

for (int i = myArray.Length - 1; i >= 0; i--)
{
    // Do something
    myArray[i] =          


        
14条回答
  •  青春惊慌失措
    2020-11-28 01:50

    In C++ you basicially have the choice between iterating using iterators, or indices. Depending on whether you have a plain array, or a std::vector, you use different techniques.

    Using std::vector

    Using iterators

    C++ allows you to do this using std::reverse_iterator:

    for(std::vector::reverse_iterator it = v.rbegin(); it != v.rend(); ++it) {
        /* std::cout << *it; ... */
    }
    

    Using indices

    The unsigned integral type returned by std::vector::size is not always std::size_t. It can be greater or less. This is crucial for the loop to work.

    for(std::vector::size_type i = someVector.size() - 1; 
        i != (std::vector::size_type) -1; i--) {
        /* std::cout << someVector[i]; ... */
    }
    

    It works, since unsigned integral types values are defined by means of modulo their count of bits. Thus, if you are setting -N, you end up at (2 ^ BIT_SIZE) -N

    Using Arrays

    Using iterators

    We are using std::reverse_iterator to do the iterating.

    for(std::reverse_iterator it(a + sizeof a / sizeof *a), itb(a); 
        it != itb; 
        ++it) {
        /* std::cout << *it; .... */
    }
    

    Using indices

    We can safely use std::size_t here, as opposed to above, since sizeof always returns std::size_t by definition.

    for(std::size_t i = (sizeof a / sizeof *a) - 1; i != (std::size_t) -1; i--) {
       /* std::cout << a[i]; ... */
    }
    

    Avoiding pitfalls with sizeof applied to pointers

    Actually the above way of determining the size of an array sucks. If a is actually a pointer instead of an array (which happens quite often, and beginners will confuse it), it will silently fail. A better way is to use the following, which will fail at compile time, if given a pointer:

    template char (& array_size(T(&)[N]) )[N];
    

    It works by getting the size of the passed array first, and then declaring to return a reference to an array of type char of the same size. char is defined to have sizeof of: 1. So the returned array will have a sizeof of: N * 1, which is what we are looking for, with only compile time evaluation and zero runtime overhead.

    Instead of doing

    (sizeof a / sizeof *a)
    

    Change your code so that it now does

    (sizeof array_size(a))
    

提交回复
热议问题