※ 개인적인 공부를 위해 포스팅 하는 글입니다.
▶ 람다 ◀
함수 객체를 빠르게 만드는 문법
람다 자체로 C++11에 새로운 기능이 들어간 것은 아니다
#실습 준비코드
#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
using namespace std;
enum class ItemType
{
None,
Armor,
Weapon,
Jewelry,
Consumable
};
enum class Rarity
{
Common,
Rare,
Unique
};
class Item
{
public:
Item() {}
Item(int itemId, Rarity rarity, ItemType type) : _itemId(itemId), _rarity(rarity), _type(type)
{
}
public:
int _itemId = 0;
Rarity _rarity = Rarity::Common;
ItemType _type = ItemType::None;
};
int main()
{
vector<Item> v;
v.push_back(Item(1, Rarity::Common, ItemType::Weapon));
v.push_back(Item(2, Rarity::Common, ItemType::Armor));
v.push_back(Item(3, Rarity::Rare, ItemType::Jewelry));
v.push_back(Item(4, Rarity::Unique, ItemType::Weapon));
}

※ 임시 객체 만들어 넣어주는거라 지난 포스팅에서 다룬 R-Value참조가 내부적으로 되어있는 모습
# 람다가 나오기 전
struct IsUniqueItem
{
bool operator()(Item& item)
{
return item._rarity == Rarity::Unique;
}
};
std::find_if(v.begin(), v.end(), IsUniqueItem());
ㆍ 이런식으로 함수객체를 만들어줘서 넣어줬을것이다... 저 IsUniqueItem은 어쩌면 한번 쓰고 다시는 안쓸놈인데도 저렇게 함수를 만들어줘서 해야하는게 좀 귀찮다.
이럴 때 람다를 쓰자
std::find_if(v.begin(), v.end(), [](Item& item) {return item._rarity == Rarity::Unique; });
ㆍ 위 코드와 같은 말이다. 이름이 없는 익명함수
[캡처목록](매개변수 목록) -> 반환타입 { 함수 본문 }
ㆍ 반환 타입은 생략 가능. 컴파일러가 추론해준다.
//[클로저] (closure) = 람다에 의해 만들어진 런타임 객체
auto IsUniqueLamda = [](Item& item) ->bool {return item._rarity == Rarity::Unique; };
std::find_if(v.begin(), v.end(), IsUniqueLamda);
ㆍ 이렇게도 넣어줄 수 있다.
# 캡처 영역을 보기 위해 한번 더 해보자 이번엔 아래경우
struct FindItemByItemId
{
FindItemByItemId(int itemId) :_itemId(itemId)
{
}
int _itemId;
bool operator()(Item& item)
{
return item._itemId == _itemId;
}
};
int itemId = 4;
auto findIt = std::find_if(v.begin(), v.end(), FindItemByItemId(itemId));
if (findIt != v.end())
{
cout << "아이템 아이디 : " << findIt->_itemId << endl;
}
ㆍ 위 코드를 람다형식으로 바꿔봤다..
auto findByItemIdLamda = [=](Item& item) {return item._itemId == itemId; };
ㆍ 캡처모드는 값방식 ( = ), 참조방식( & ) 두가지가 있다. 말 그대로 스냅샷을 찍는다고 이해하자.
ㆍ 값방식 참조방식은 뭐 알고있는 그대로다. 복사할건지,원본객체 할건지
auto findByItemIdLamda = [=](Item& item) {return item._itemId == itemId; };
auto findIt = std::find_if(v.begin(), v.end(), findByItemIdLamda);
if (findIt != v.end())
{
cout << "아이템 아이디 : " << findIt->_itemId << endl;
}
ㆍ 동일한 결과가 실행된다.
auto findByItemIdLamda = [itemId, &rarity](Item& item) {return item._itemId == itemId; };
ㆍ 이런식으로 전체가 아니라 각각 변수마다도 캡처를 지정해 줄 수도 있다.
ㆍ C++에서는 기본 캡처모드(전체캡처) 를 사용하지 않는것을 권고한다. 그러므로 어떤것을 캡처할거고, 값으로할건지 참조로 할건지 꼭 정해주도록 하자.
ㆍ 전체 캡처를 남발하면 주소가 해제되었을때.... 예상하지 못한 버그가 발생할 경우가 있을 수 있겠다. .
class Knight
{
public:
auto ResetHpJob()
{
auto f = [this]()
{
this->_hp = 200;
};
return f;
}
public:
int _hp;
};
Knight* k = new Knight();
auto job = k->ResetHpJob();
delete k;
job();
ㆍ 맨아래 두줄... 저 상황이 진짜위험하다. 지금 당장 프로그램이 터지지 않아도 메모리가 계속 오염될거다
'C++프로그래밍 > 모던C++' 카테고리의 다른 글
shared_ptr 구현해보기 (0) | 2024.10.03 |
---|---|
전달 참조(forwarding reference) [(구)(universal reference)] (0) | 2024.10.02 |
오른값 참조(rvalue)와 std::move (1) | 2024.10.02 |
delete (삭제된 함수) (0) | 2024.10.02 |
using문과 enum class (1) | 2024.10.02 |