*람다 표현식 ( lambda expression )
[ 캡처 ] ( 매개변수 ) { 구현부 } => '리턴값 자동 추론'
[ 캡처 ] ( 매개변수 ) -> 리턴값 { 구현부 }
vector<Item> vec;
auto findIt = std::find_if(vec.begin(), vec.end(),
[ ](Item& item)
{
return item.Rarity == Rarity::Unique;
});
*[ ] 캡처 ( capture )
=> 함수 객체 내부에 변수를 저장하는 개념과 유사
* [&] : call-by-reference 와 유사
=> 외부의 모든 변수들의 주소를 가져온다.
int a = 4;
auto Changed = [&]() { a = 5; };
=> 참조를 사용할 땐 값이 바뀔 수 있음을 인지해야함. 항상 조심 ( 주소값 참조 )
* [=] : call-by-value 와 유사
=> 외부의 모든 변수들의 값을 가져온다.
int a = 4;
auto IsCheck = [=]() { return a == 1; };
a = 10;
*값 캡처는 언제 값이 복사가 되는가 ??
int v = 42;
auto func = [=] { cout << v << endl; };
v = 8;
func();
=> 42
=> 클로저 객체가 '생성되는 시점' 에서 v 의 값을 가져온다.
=> 또한, 값 캡처가 된 값들은 자동적으로 'const' 가 된다. ( 상수화 )
*const 된 값들을 바꿀 수 있을까 ??
=> mutable
int v = 42;
auto func = [=] () mutable
{
v += 8;
cout << v << endl;
};
func();
=> 실제 외부의 v 값은 바뀌지 않음.
* 변수마다 캡처모드를 지정해서 사용 가능.
int a = 1, b = 2, c = 3;
int Sum = 0;
auto Changed = [&a, b, c, &Sum]()
{
a = 10;
Sum = b + c;
};
=> 기본적인 값, 참조 ( [&, = ] ) 캡처모드는 지양.
=> 사용할 변수들 각각 캡처모드를 지정해서 사용.
*클래스 안에서의 값 캡처
struct foo {
foo() : i(0) {}
void amazing() {
[=] { i = 8; }();
}
int i;
};
foo f;
f.amazing();
cout << "f.i : " << f.i;
=> 클래스 안에서 [=] 하게 되면,
암묵적으로 클래스의 this 를 복사함으로써,
클래스 멤버변수 i 에 접근 가능하게 된다.
*캡처의 범위
int i = 8;
auto f = [=]() {
int j = 2;
auto m = [&] { i /= j; };
m();
cout << "inner: " << i;
};
f();
cout << " outer: " << i;
=> 캡처되는 변수들은 람다가 접근 가능한 위치에 있어야 함.
*클로저 ( closure ) => 람다에 의해 만들어진 실행시점 객체 ( isUniqueLambda )
class Player
{
public:
Player() {}
~Player() {}
Player(const Player& other)
{
Data = other.Data;
cout << "복사생성자" << endl;
}
Player& operator=(const Player& other) { cout << "복사대입연산자" << endl; }
int Data = 101;
};
Player P1, P2, P3;
int Sum = 0;
auto SumPlayerData = [=, &Sum]()
{
Sum += P1.Data;
Sum += P2.Data;
Sum += P3.Data;
};
SumPlayerData();
cout << Sum << endl;
=> 클래스 [ = ] 값 캡처 시, 복사생성자 호출
*결론
어떤 행동을 저장해 내가 원하는 시점에 제어하기 위해서,
함수포인터, functor 를 이용해 굉장히 많은 작업을 했어야했지만
람다식으로 인해 효율성 증가.
transform, for_each, find_if ... 등 C++ 의 다양한 기능에 접목시켜 활용 가능.
[ = ] , [ & ] 는 지양.
개별로 각기 캡처를 받아 사용하는 것이 바람직.
값이 어떻게 변하는지 항상 유의.
참고 링크
본 내용은 인프런의 루키스님 강의를 듣고 정리한 내용입니다.
'프로그래밍 > C++' 카테고리의 다른 글
@.NET Framework (0) | 2022.08.27 |
---|---|
#69. c++ 스마트 포인터 ( smart pointer ) (0) | 2022.07.23 |
#67. 전달 참조 ( forwarding reference ) (0) | 2022.07.22 |
#66. 오른값참조 ( rvalue reference ) (0) | 2022.07.22 |
#65. enum class & override & final (0) | 2022.07.22 |