2

I try to find the min and max value in a array (size is n) use 3 * (n // 2) times comparison in once ergodic. And this is my code:

#include <iostream>
#include <initializer_list>
//!
//! @Brief:get the minmum and maxmum in 3 * ( n // 2) times comparison.
//! Create by Soyn. 31/7/15.
//!

    bool IsOdd( size_t n)
    {
        return n % 2 ;
    }
    std::initializer_list<int> getLargerAndSmaller( int a, int b)
    {
        if(a <= b){
            return {a,b};
        }else{
            return {b,a};
        }
    }

    int main(void)
    {
        int  Min, Max;
        int a[] = {5,4,1,7,3,8,3,4,9,10};
        int n = sizeof(a) / sizeof(a[0]);
        for( int i = 0; i < n - 1; i += 2){
            if( (i ==0) &&IsOdd(n)){           // initialize the Min and Max.
                Min = Max = a[i];
            } else{
                    auto item = getLargerAndSmaller(a[i],a[i+1]);
                    if(i == 0){
                            Min = *(item.begin());
                            Max = *(item.begin() + 1);
                            std :: cout << "Min: " << Min << " , " << "Max: " << Max << std :: endl;
                        }else{
                        std :: cout << *(item.begin()) << " , " << *( item.begin() + 1) << std :: endl;
                        Min > *(item.begin()) ? Min = *(item.begin()) : Min;
                        Max < *(item.begin() + 1) ? Max = *(item.begin() + 1) : Max;
                        std :: cout << "Min: " << Min << " , " << "Max: " << Max << std :: endl;
                        }
            }
        }
         return 0;
    }

For testing my code, I add some statement in my code, like

std :: cout << *(item.begin()) << " , " << *( item.begin() + 1) << std :: endl;

and this is the point I can't figure out. When I add this, the result is wrong. If, I clear it, it works well. Following is the wrong result image:

enter image description here

WangYao
  • 79
  • 9

1 Answers1

3

It's almost never correct for a function to return std::initializer_list because they refer to a local array.

When you write return {a, b}; , or equivalently for exposition:

std::initializer_list<int> x = { a, b };
return x;

what happens is that an automatic (stack) array of 2 elements is created, containing copies of a and b; and the initializer_list object holds a reference to that local array.

So when you access item you're accessing a dangling reference (undefined behaviour).


initializer_list wasn't designed to be used as a container - use array or vector or pair etc. instead.

M.M
  • 138,810
  • 21
  • 208
  • 365
  • But when i cout the *(item.begin()) and *(item.brgin() + 1), it is a right value. It just can't enter this statement ` Min > *(item.begin()) ? Min = *(item.begin()) : Min; Max < *(item.begin() + 1) ? Max = *(item.begin() + 1) Max; ` – WangYao Jul 31 '15 at 05:16
  • 1
    @WangYao [undefined behaviour](http://stackoverflow.com/a/4105123/1505939) means that anything can happen. Including what you see, and everything else. Probably the calls to `cout <<` overwrite the memory area where the initializer list's storage was. – M.M Jul 31 '15 at 05:55