CPP/c++실전사용법

pair와 tuple(C++)(알고리즘) (find,find_if, 람다식 캡쳐절)

뜨거운 개발자 2022. 12. 29. 09:05

위 글은 큰돌의 터전 님의 강의자료를 참조해서 정리하고 제가 알고리즘을 풀면서 더 추가적으로 사용할 만한 내용들을 정리한 글입니다.

알고리즘 풀이 강의로 큰돌의 터전님의 강의 강력 추천드립니다.

강의링크

pair와 tuple

pair와 tuple은 타입이나 자료구조는 아닙니다. C++에서 제공하는 utility 라이브러리 헤더의 템플릿 클래스이며 자주 사용되기 때문에 알아보겠습니다.

pair는 first와 second 라는 멤버변수를 가지는 클래스입니다. 두가지 값을 담아야 할 때 씁니다. tuple은 세가지 이상의 값을 담을 때 씁니다. 여기서 tie는 pair이나 tuple로부터 값을 끄집어낼 때 사용되는 함수입니다.

#include<bits/stdc++.h>
using namespace std;
pair<int, int> pi; 
tuple<int, int, int> tl; 
int a, b, c;

int main(){ 	
    pi = {1, 2}; 		
    tl = make_tuple(1, 2, 3); 	
    tie(a, b) = pi; 	
    cout << a << " : " << b << "\n"; 
    tie(a, b, c) = tl; 	
    cout << a << " : " << b << " : "<< c << "\n"; 	
    return 0; 
}

pair의 경우 {a, b} 또는 make_pair(a, b)로 만들 수 있습니다.

원래는 a = pi.first; b = pi.second 이런식으로 끄집어내야 하는데 tie를 쓰게 되면 tie(a, b) = pi 이렇게 끄집어 낼 수 있습니다.

다음 코드는 tie를 쓰지 않는 코드입니다.

pair은 first, second로 값을 끄집어 내며, tuple같은 경우 get<0> .. 이런식으로 값을 꺼내야 합니다.

#include<bits/stdc++.h>
using namespace std;
pair<int, int> pi; 
tuple<int, int, int> ti; 
int a, b, c; 
int main(){ 	
    pi = {1, 2}; 	
    a = pi.first; 		
    b = pi.second; 		
    cout << a << " : " << b << "\n"; 
    ti = make_tuple(1, 2, 3); 	
    a = get<0>(ti); 	
    b = get<1>(ti); 	
    c = get<2>(ti); 		
    cout << a << " : " << b << " : "<< c << "\n"; 	
    return 0; 
} 
/*
1 : 2 
1 : 2 : 3 
*/

auto키워드

auto 타입은 복잡하고 긴 타입의 변수명을 대신하는 간단한 방법입니다. 예를 들어 다음 코드처럼 pair<int, int> it가 아닌 auto it로 조금 더 짧게 선언되는 것을 볼 수 있습니다

#include<bits/stdc++.h> 
using namespace std; 
int main()
{ 	
    vector<pair<int, int>> v; 
    for(int i = 1; i <= 5; i++){ 	
        v.push_back({i, i}); 	
    } 	
    for(auto it : v)
    { 		
        cout << it.first << " : " << it.second << '\n'; 
    } 	
    for(pair<int, int> it : v)
    { 	
        cout << it.first << " : " << it.second << '\n'; 
    } 	
    return 0; 
} 

/* 
1 : 1
2 : 2 
3 : 3
4 : 4
5 : 5 
1 : 1
2 : 2 
3 : 3
4 : 4
5 : 5 
*/

pair의 화살표 연산자

#include<bits/stdc++.h>
using namespace std; 
pair<int, int> a = {1, 2}; 
int main()
{ 	
    pair<int, int> * b = &a; 	
    cout << b -> first << "\n"; 
    cout << (*b).first << "\n"; 
    return 0; 
} 
/* 
1 
1 
*/

find와 find_if()

find 함수

template <class InputIterator, class T>
InputIterator find(InputIterator first, InputIterator last, const T& val);

와 같은데 이건 맨 마지만 val 인자의 타입 T에 ==이 정의 되어 있어야만 사용할 수 있다.

하지만 pair같은 경우 first 와 second를 비교 할 거라서 꼭 find_if()함수를 써줘야만 한다.

find_if() 함수

template <class InputIterator, class UnaryPredicate>
InputIterator find_if(InputIterator first, InputIterator last, \\
UnaryPredicate pred);

맨 마지막 pred 인자에 내가 원하는 조건식(bool 리턴값을 가지는)을 작성해서 넣어주면 됩니다.

pair 구조체에는 operator== 가 정의되어 있지 않아서 find를 사용하면 같은 값을 찾을 수 없습니다.

틀린코드

auto a = find(arr.begin(),arr.end(),num);

수정 코드

auto a = find_if(arr.begin(),arr.end(), \\
	[&num](const pair<int, int>& elem){ return elem.first == num;});

수정 된 코드를 보면 아에 모르는 개념이 등장하는데 [&num] 이게 뭐냐?

C++11 이상에서 람다 식(종종 람다 라고도 함)은 함수에 인수로 호출되거나 전달되는 위치에서 익명 함수 개체( 클로저 )를 정의하는 편리한 방법입니다. 일반적으로 람다는 알고리즘 또는 비동기 함수에 전달되는 몇 줄의 코드를 캡슐화하는 데 사용됩니다.

람다식

  1. capture 절 (C++ 사양의 람다 소개자 라고도 함)
  2. 매개 변수 목록 선택적. ( 람다 선언자라고도 함)
  3. 변경 가능한 사양 선택적.
  4. exception-specification 선택적.
  5. trailing-return-type 선택적.
  6. 람다 본문입니다.

Capture 절

[ ] 이렇게 빈 캡쳐절을 사용하는 건 람다 식의 본문이 바깥쪽 범위 변수에 엑세스 하지 않는 것을 의미합니다.

그리고 이 안에 넣는 변수가 [&A] 로 넣을수도 있고 [A] 이렇게 값으로 엑세스 할 수도 있다. 그 외에 이렇게도 사용이 가능한데

[&total, factor]
[factor, &total]
[&, factor]
[=, &total]

https://learn.microsoft.com/ko-kr/cpp/cpp/lambda-expressions-in-cpp?view=msvc-170 

 

C++ 람다 식

자세한 정보: C++의 람다 식

learn.microsoft.com

이 이상의 내용은 레퍼런스를 참고하도록 하자.

728x90