이미 한번 했었더라 ,,, 근데 까먹어서 다시 정리하기!! https://velog.io/@yangju058/STL-연산자-오버로딩
함수객체란, ()연산자를 오버로딩한 객체를 의미한다
주로 '함수처럼 동작하는 클래스 객체'라고도 한다
-> 이 의미가 그냥 함수형태처럼 호출할 수 있다는 것이다
보통 멤버함수를 호출하려면 객체명.함수이름(인자);로 호출하는데, 함수 객체를 사용하면 객체명(인자); 로 바로 호출할 수 있게된다
-> operator()에 정의해둔 로직이 호출되는 것
일반 클래스 객체와 동일하게 서로 다른 함수 객체를 생성하면, 별개의 객체이기 때문에 멤버 변수도 서로 다른 값을 가진다
#include <iostream>
using namespace std;
class Adder
{
public:
int operator()(int a, int b)
{
return a + b;
}
};
int main()
{
Adder add;
cout << "함수객체로 호출1 : " << add(5, 4) << endl;
cout << "함수객체로 호출2 : " << add.operator()(5, 4) << endl;
return 0;
}

함수 객체는 멤버 변수를 가질 수 있고, 상태 유지가 가능하다!
상태 유지 : 함수 객체를 호출할 때 멤버 변수의 값에 변동을 준다면 그 상태가 계속 유지되는 상태
-> 함수 객체 자체가 클래스에서 생성되었기 때문에 상태를 가진다 (멤버 변수 값을 변경하여 동작이 가능함)
상태를 가진다는 게, 함수 객체 자체가 클래스에서 생성된 객체니까 멤버 변수를 가지고 있는 상태를 의미함
sum에 값이 누적된다#include <iostream>
using namespace std;
class Adder
{
private:
int sum;
public:
Adder()
{
sum = 0;
}
void operator()(int value)
{
sum += value;
cout << "현재 합 : " << sum << endl;
}
const int& Sum()
{
return sum;
}
};
int main()
{
Adder add;
add(10);
add(10);
add(10);
cout << "멤버변수 count의 값 : " << add.Sum() << endl;
return 0;
}
출력값 :
근데 멤버 변수의 상태가 유지되는 것은 일반 멤버 함수도 가능한 일이다
위의 예시 코드에서 ()연산자를 일반 멤버 함수로 바꾸고, 객체를 활용하여 함수를 호출하였다
-> 보다시피 값이 누적되었고, 최종적인 멤버변수의 값도 누적된 값 그대로이다
만약, 멤버 변수가 static으로 선언되어있을 경우
-> 클래스 객체가 같은 변수를 공유하기 때문에 별개의 객체별로 다른 값을 저장할 수 없다
-> 객체가 여러개여도 멤버 변수값이 공유되어 다 같은 멤버 변수가 된다

전역함수에 static으로 선언한 정적변수가 있을 경우, 함수를 호출할때마다 값이 유지된다
일반 변수인 경우 전역함수를 여러번 호출해도 매번 새로운 값이고 유지되지 않는다

여러 방법으로도 다 상태유지는 가능한데 왜 함수 객체를 써야하는 걸까? 공부하면서 많이 궁금했다
일반적인 클래스 객체는 데이터 저장, 멤버 함수로 기능을 수행한다
함수 객체는 주로 STL함수를 사용할 때 많이 쓴다
-> 우리는 이미정의된 클래스를 사용하여 STL함수를 사용하지만, 함수 객체가 정확히 뭔지 무엇을 뜻하는지는 알고 쓰는 것이 좋다고 생각해서 이해했다


less와greater는 C++ STL에 포함된 함수객체(Functor)이다
-> 주로 정렬, 비교 연산에서 사용된다
(sort(),map,priority_queue)
오름차순 정렬을 할때 사용된다
std::less는 두 값이 '왼쪽이 오른쪽보다 작다'는 조건을 비교하는 함수 객체임
less<T>()-> 여기서 T는 템플릿으로 자료형을 지정하라 는 의미
less<T>() 사용예시오름차순으로 정렬할때 sort함수를 사용하는데, sort(시작, 끝, 함수객체); 로 선언한다
sort함수를 사용하기 위해서 #include <algorithm>
less함수를 사용하기 위해서 #include <functional>
sort함수를 사용할때는 less함수객체를 사용하지 않더라도 기본적으로 오름차순이다
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional> // std::less
using namespace std;
int main()
{
vector<int> vec = { 10, 2, 30, 4, 15 };
// less 함수 객체를 이용한 오름차순 정렬
sort(vec.begin(), vec.end(), less<int>());
// 정렬된 벡터 출력
for (int i = 0; i < vec.size(); i++)
{
cout << vec[i] << " ";
}
cout << endl;
return 0;
}
내림차순 정렬을 할때 사용된다
std::greater는 두 값이 '왼쪽이 오른쪽보다 크다'는 조건을 비교하는 함수 객체임
사용 방법 :greater<T>()
greater<T>() 사용예시#include <iostream>
#include <vector>
#include <algorithm>
#include <functional> // std::greater
using namespace std;
int main()
{
vector<int> vec = { 10, 2, 30, 4, 15 };
// greater 함수 객체를 이용한 내림차순 정렬
sort(vec.begin(), vec.end(), greater<int>());
// 정렬된 벡터 출력
for (int i = 0; i < vec.size(); i++)
{
cout << vec[i] << " ";
}
cout << endl;
return 0;
}
사용자 정의 template 클래스를 하나 만들고 안에 operator()연산자를 사용하여 a < b라면 true를 반환하는 로직을 정의했다
함수 객체 less안에 이미 a < b를 반환하는 로직을 정의해두었기 때문에 sort함수 내에 사용할 경우 적용된다
아직 sort함수의 내부구조에 대해서는 다뤄보지 않았기 때문에, 정확환 과정은 모르지만
-> sort함수 내부의 두 값을 가져와서 less 객체를 호출하고, 호출된 operator가 두 값을 비교한다 라고 이해해두자
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional> // std::greater
using namespace std;
template <typename T>
class Less
{
public:
bool operator() (const T& a, const T& b)
{
return a < b;
}
};
int main()
{
Less<int>less; // 함수객체 생성
vector <int> vector = { 1, 2, 3, 4, 5 };
sort(vector.begin(), vector.end(), less);
for (int i = 0; i < vector.size(); i++)
{
cout << vector[i] << " ";
}
return 0;
}

사진 출처 : https://programmerpsy.tistory.com/52
plus<T>() & minus<T>() 예시#include <iostream>
#include <vector>
#include <algorithm>
#include <functional> // std::greater
using namespace std;
struct Plus
{
int operator() (int a, int b)
{
return a + b;
}
};
int main()
{
cout << "(일반적인 사용) 더하기 : " << plus<int>()(10, 20) << endl;
Plus pluss;
cout << "(함수객체 사용) 더하기 : " << pluss(10, 20) << endl;
cout << "(명시적 호출) 더하기 : " << pluss.operator()(10, 20) << endl; // 명시적 호출
cout << "빼기 : " << minus<int>()(20, 10);
return 0;
}
함수 객체를 사용하는 이유

다양한 STL 알고리즘에서 사용된다
기준점은 무조건 앞에오는 a다.
a > b : 내림차순
➡ a가 b보다 크다면 a가 앞에온다. 즉, a > b 조건이 맞다면 a가 앞에 온다는 것
a < b : 오름차순
➡ a가 b보다 작다면 a가 앞에온다. 즉, a < b 조건이 맞다면 a가 앞에 온다는 것
bool Less(const int & a, const int & b)
{
return a < b; // 오름차순
}
bool Greater(const int& a, const int& b)
{
return a > b; // 내림차순
}
int main()
{
vector<int>v;
v.push_back(10);
v.push_back(40);
v.push_back(30);
v.push_back(20);
v.push_back(50);
sort(v.begin(), v.end(), Less); // 오름차순
for (int& c : v) cout << c << " "; // 10 20 30 40 50
sort(v.begin(), v.end(), Greater); // 내림차순
for (int& c : v) cout << c << " "; // 50 40 30 20 10
}