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;
}
10
  • 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. Commented Aug 19, 2017 at 6: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. Commented Aug 19, 2017 at 6:21
  • 1
    Off topic: Rather than ` std::vector<int> a; int b[] = {11,8,7,6,4,3,4,1};` and a for loop to copy, assign directly to the vector: std::vector<int> a = {11,8,7,6,4,3,4,1}; Commented Aug 19, 2017 at 6:24
  • On topic: What's the difference between passing by reference vs. passing by value? Commented Aug 19, 2017 at 6:25
  • 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. Commented Aug 19, 2017 at 6:35

1 Answer 1

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;
}
Sign up to request clarification or add additional context in comments.

2 Comments

The most straightforward, and idiomatic way to solve this is with a std::reference_wrapper. This is precisely the purpose for which it exists.
Can argue with that, but I'd be stupid to. You have raisins, @BenjaminLindley . One more edit coming up.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.