0

I wrote the code like the below, I don't know why the member variable flag did't equal 1 after sort process? Can someone give me suggestion.

Code:

class Func{
public:
    int flag;
    Func()
    {
        flag = 0;
    }
    bool operator()(int &l, int &r)
    {
        if(l==r)
        {
            flag = 1;   
        }
        return l > r;
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    vector<int> a;
    int b[] = {11,8,7,6,4,3,4,1};
    for(int i = 0; i <sizeof(b)/sizeof(b[0]); i++)
    {
        a.push_back(b[i]);
    }

    Func FuncObj = Func();
    std::sort(begin(a), end(a), FuncObj);
    return 0;
}
Ely
  • 10,860
  • 4
  • 43
  • 64
  • 1
    You say `flag` was not `1` after sorting, but your code never reads `flag` at all. Post your actual code that demonstrates the problem. – John Zwinck Aug 19 '17 at 06:19
  • Flag equals to 1 only if r and l are equals, but this might not happen during sorting, even the fact that you have two 4 in the data set. – Kamen Stoykov Aug 19 '17 at 06:21
  • 1
    Off topic: Rather than ` std::vector a; int b[] = {11,8,7,6,4,3,4,1};` and a `for` loop to copy, assign directly to the vector: `std::vector a = {11,8,7,6,4,3,4,1};` – user4581301 Aug 19 '17 at 06:24
  • On topic: [What's the difference between passing by reference vs. passing by value?](https://stackoverflow.com/questions/373419/whats-the-difference-between-passing-by-reference-vs-passing-by-value) – user4581301 Aug 19 '17 at 06:25
  • i add a break in the flag = 1, it has run to it, i'm use cout << FuncObj.flag << endl, finally it print 0 – Daniel-Wang Aug 19 '17 at 06:28
  • 1
    Because `FuncObj` is passed by value. `std::sort` operates on a copy of `FuncObj`, `flag` is set to ` in the copy of `FuncObj` and `FuncObj` is unchanged. – user4581301 Aug 19 '17 at 06:35
  • By the way, good on you for using the debugger. Now inspect the address of `FuncObj` and compare it to `this` inside `operator()`. You will see that they are different objects. – user4581301 Aug 19 '17 at 06:36
  • FuncObj pass by value in sort sounds reasonable, but how to let it don't pass by value? – Daniel-Wang Aug 19 '17 at 06:38
  • @user6927970 You can't, because that would entail changing the signature of `std::sort`, which you can't do. Try marking `flag` as `static` so that it is the same no matter which instance you have. – Rakete1111 Aug 19 '17 at 06:43
  • using static member variables can work,thanks!! – Daniel-Wang Aug 19 '17 at 06:49

1 Answers1

1

According to reliable documentation, std::sort accepts the function object by value. This means the Func being used by std::sort is a copy of FuncObj. This means that when 4 is compared with 4, the copy's flag variable is set to 1, and FuncObj is unchanged. The copy is destroyed when std::sort returns, so this flag is lost.

The simplest solution define int flag as static int flag to that all instances of Func share the same Flag.

If this is not an option, different Funcs must have their own flag, my inclination was to go with a std::shared_ptr. Each default constructed Func would have had it's own flag and shared this flag with any copies made.

However Benjamin Lindley reminds of std::reference_wrapper and this provides a much more convenient solution for the problem. The wrapper is passed by value and copied rather then the Func it references, allowing the source Func to be modified inside std::sort.

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

class Func{
public:
    int flag;
    Func(): flag(0)
    {
    }
    bool operator()(int &l, int &r)
    {
        if(l==r)
        {
            flag = 1;
        }
        return l > r;
    }
};

int main()
{
    std::vector<int> a = {11,8,7,6,4,3,4,1};

    Func FuncObj = Func();
    std::sort(begin(a), end(a), std::reference_wrapper<Func>(FuncObj));
    std::cout << FuncObj.flag;
    return 0;
}
user4581301
  • 33,082
  • 7
  • 33
  • 54
  • The most straightforward, and idiomatic way to solve this is with a [`std::reference_wrapper`](http://en.cppreference.com/w/cpp/utility/functional/reference_wrapper). This is precisely the purpose for which it exists. – Benjamin Lindley Aug 19 '17 at 07:02
  • Can argue with that, but I'd be stupid to. You have raisins, @BenjaminLindley . One more edit coming up. – user4581301 Aug 19 '17 at 07:10