1. 람다(Lambda), 이름없는 함수
기존에는 find_if, sort 등의 STL의 알고리즘 사용 시, 함수 객체를 정의해야 했는데 함수 객체 정의를 할 필요가 없어졌음
2. 람다의 기본 사용 방법
[캡쳐](파라미터)->반환형{함수정의}(호출);
3. 람다 기본 사용 예시
#include <iostream>
void main()
{
auto func = [] { std::cout << "Hello, World" << std::endl; };
func();
system("pause");
}
4. 파라미터 예시
람다는 일반 함수 처럼 파라미터를 정의할 수 있음
auto func2 = []( int iX ) { std::cout << "print : " << iX << std::endl; };
func2( 111 );
func2( 222 );
func2( 333 );
5. 반환값 예시
람다는 반환값을 넘길 수 있음, 명시적, 암묵적 둘 다 가능
auto func3 = []()->float { return 3.14f; };
std::cout << func3() << std::endl;
auto func4 = [] { return 3.14; };
std::cout << func4() << std::endl;
auto func5 = [](float f) { return f; };
std::cout << func5(3.14f) << std::endl;
6. 캡처 예시
람다외부에 정의되어있는 변수를 내부에서 사용하고 싶으면 캡처 한다.
- [&] : 람다 외부 변수 모두 참조로 캡처
- [=] : 람다 외부 변수 모두 복사로 캡처
- 변수 하나만 캡처 시 아래와 같이 사용
int iExam1 = 0;
auto func6 = [iExam1] { std::cout << "iExam1 : " << iExam1 << std::endl; }; // 복사로 캡처
func6();
auto func7 = [&iExam1] { std::cout << "iExam1 : " << iExam1 << std::endl; }; // 참조로 캡처
func7();
참초로 캡처 시 해당 변수를 람다 내부에서 변경 가능
int iTotal = 0;
auto func8 = [&] { iTotal++; std::cout << "iTotal : " << iTotal << std::endl; };
func8();
복사로 캡처 시 해당 변수를 람다 함수 내부에서 변경하면 아래와 같이 에러 발생
auto func9 = [=] { iTotal++; std::cout << "iTotal : " << iTotal << std::endl; };
func9(); // error C3491: 'iTotal': 변경 불가능한 람다에서 복사 방식 캡처를 수정할 수 없습니다.
복사로 캡처한 변수를 람다 내부에서 변경해야 한다면 아래와 같이 mutable 사용
auto func9 = [=] () mutable{ iTotal++; std::cout << "iTotal : " << iTotal << std::endl; };
func9();
아래와 같이 혼합해서 사용 가능
int iNum1 = 1, iNum2 = 2;
auto func10 = [iNum1, &iNum2]() mutable { std::cout << "iNum1 : " << iNum1 << " iNum2 : " << iNum2 << std::endl; };
func10();
전체 코드
#include <iostream>
#include <functional>
#include <algorithm>
void main()
{
std::function<void(void)> func1 = []{ std::cout << "Hello, World" << std::endl; };
func1();
auto func = [] { std::cout << "Hello, World" << std::endl; };
func();
auto func2 = []( int iX ) { std::cout << "print : " << iX << std::endl; };
func2( 111 );
func2( 222 );
func2( 333 );
auto func3 = []()->float { return 3.14f; };
std::cout << func3() << std::endl;
auto func4 = [] { return 3.14; };
std::cout << func4() << std::endl;
auto func5 = [](float f) { return f; };
std::cout << func5(3.14f) << std::endl;
int iExam1 = 0;
auto func6 = [iExam1] { std::cout << "iExam1 : " << iExam1 << std::endl; }; // 복사로 캡처
func6();
auto func7 = [&iExam1] { std::cout << "iExam1 : " << iExam1 << std::endl; }; // 참조로 캡처
func7();
int iTotal = 0;
auto func8 = [&] { iTotal++; std::cout << "iTotal : " << iTotal << std::endl; };
func8();
auto func9 = [=] () mutable{ iTotal++; std::cout << "iTotal : " << iTotal << std::endl; };
func9();
int iNum1 = 1, iNum2 = 2;
auto func10 = [iNum1, &iNum2]() mutable { std::cout << "iNum1 : " << iNum1 << " iNum2 : " << iNum2 << std::endl; };
func10();
system("pause");
}
7. STL의 알고리즘에서의 람다 사용
상황 : 죽은 유저를 찾는 상황에서의 find_if 알고리즘 사용
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
class User
{
private :
int m_Index;
bool m_bDie;
public :
User() : m_bDie(false) {}
~User(){}
void SetIndex( int Index ) { m_Index = Index; }
int GetIndex() { return m_Index; }
void SetDie() { m_bDie = true; }
bool IsDie() { return m_bDie; }
};
void main()
{
vector<User> Users;
User User01;
User01.SetIndex( 1 );
User User02;
User02.SetIndex( 2 );
User02.SetDie(); // 죽은 유저
User User03;
User03.SetIndex( 3 );
Users.push_back( User01 );
Users.push_back( User02 );
Users.push_back( User03 );
vector<User>::iterator Iter = find_if( Users.begin() , Users.end(), [](User& tUser)->bool{ return tUser.IsDie(); } );
cout << "Dead User Index : " << Iter->GetIndex() << endl;
system("pause");
}
만약 람다를 사용하지 않으면 코드는 아래와 같이 만들어야함
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
class User
{
private :
int m_Index;
bool m_bDie;
public :
User() : m_bDie(false) {}
~User(){}
void SetIndex( int Index ) { m_Index = Index; }
int GetIndex() { return m_Index; }
void SetDie() { m_bDie = true; }
bool IsDie() { return m_bDie; }
};
struct FindDeadUser
{
bool operator() ( User& tUser ) const
{
return tUser.IsDie();
}
};
void main()
{
vector<User> Users;
User User01;
User01.SetIndex( 1 );
User User02;
User02.SetIndex( 2 );
User02.SetDie(); // 죽은 유저
User User03;
User03.SetIndex( 3 );
Users.push_back( User01 );
Users.push_back( User02 );
Users.push_back( User03 );
vector<User>::iterator Iter = find_if( Users.begin(), Users.end(), FindDeadUser() );
cout << "Dead User Index : " << Iter->GetIndex() << endl;
system("pause");
}