ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • C++ Primer CH10. Generic Algorithms
    c++ 2024. 1. 21. 16:26

    알고리즘 함수 종류는 100여개가 넘는다. 다 외우기 힘드니까 분류를 해보자

    10.2.1 Read-Only Algorithms

    10.2.2 Write Container Elements Algorithms

    10.2.3 Reorder Container Algorithms

    10.3 Customizing Operations

    10.3.1 Passing a Function to an Algorithm

    predicates

    조건으로 활용될 수 있는 expression(표현식), 함수

    10.3.2 Lambda Expressions

    이름 없는 inline 함수라고 생각하면 된다.

    Lambda 형태

    [capture list](parameter list) -> return type { function body }
    
    [sz](const string &a) {return a.size() >= sz; };
    

     

    for_each Algorithms

    auto wc = find_if(words.begin(), words.end(),
    		[sz](const string &a) { return a.size() >= sz; }); // lambda 함수 조건을 만족하는 첫번째 원소의 이터레이터 반환
    auto count = words.end() - wc;
    cout << count << " " << make_plural(count, "word", "s")
    			<< " of length " << sz << " or longer" << endl;
    
    for_each(wc, words.end(), [](const string &s){cout << s << " ";});
    // wc는 sz보다 크기 큰 첫번째 이터레이터 ~ end() 사이 원소에 대해 3번째 lambda 함수 수행
    

    10.3.3 Lambda Captures and Returns

    lambda는 인자로 들어갈 때 컴파일러가 알아서 이름 없는 클래스의 객체로 만들어준다.

    lambda의 리턴값의 타입을 auto로 해주면 컴파일러가 알아서 자동생성된 클래스 타입으로 지정해준다.

     

    Capture by Value

    lambda의 capture 변수는 lambda 생성시 복사되어 lambda에 들어간다.

    → 함수 파라미터가 호출됐을 때 복사되는 것과는 대조된다.

    void fnc1() {
    	size_t v1 = 42;
    	auto f = [v1]{return v1;};
    	v1 = 0;
    	auto j = f(); // j는 42이다. v1이 lambda에게 42로 복사되었고, 이걸 반환하기 때문
    

     

    Capture by Reference

    void fnc1() {
    	size_t v1 = 42;
    	auto f = [&v1]{return v1;};
    	v1 = 0;
    	auto j = f(); // j는 0이다. 캡처에 v1의 참조자가 들어갔기 때문. return v1은 바인딩된 객체의 값을 반환함
    

    주의할 점

    • 참조자를 캡처할 경우, 람다가 실행되는 동안 참조자가 유효해야 한다.
    • 참조자나 포인터를 캡처 안하는게 좋다

    Implicit Captures

    람다의 바디를 보고 컴파일러가 알아서 어떤 변수를 캡처링해야하는지 추론하도록 하는 것

    참조자 추론: [&] → 필요한 변수들을 모두 참조자로 불러옴

    값 추론: [=] → 필요한 변수들을 모두 값으로 불러옴

    implicit, explicit 섞어 쓸 수도 있다.

    void biggies(vector<string> &words,
    							vector<string>::size_type sz,
    							ostream &os = cout, cahr c = ' ')
    {
    	for_each(words.begin(), words.end(), [&, c, ..., (identifiers)](const string &s) { os << s << c; });
    	for_each(words.being(), words.end(), [=, &os, ..., (참조자들))(const string &s) }os << s << c; });
    }
    

     

    Mutable Lambdas

    captured by value 들을 변경할 수 있게 하려면, mutable 키워드를 붙이면 된다.

     

    Specifying the Lambda Return Type

    lambda는 기본적으로 conditional operator의 타입 추론을 통해 반환 타입이 추론된다.

     

    타입을 지정하는 법 → trailing return type

    transform(vi.begin(), ve.end(), vi.begin(), [](int i) -> int
    		{ if (i < 0) return i; else return i; });
    

    10.3.4 Binding Arguments

    한정된 인자 개수의 함수가 있을 때, 추가 변수를 넘겨주고 싶다면 어떻게 해야 하는지? → bind function 사용

    bind 함수의 정의된 위치: functional header

    auto newCallable = bind(callable, arg_list);
    
    // lambda
    auto wc = find_if(words.begin(), words.end(),
    				[sz](const string &a)
    
    // bind
    auto wc = find_if(words.begin(), words.end(),
    			bind(check_size, _1, sz));
    
    auto g = bind(f, a, b, _2, c, _1);
    g(X,Y) == f(a, b, Y, c, X)
    

     

    인자 순서를 바꿔주고 싶을 때

    sort(words.begin(), words.end(), bind(isShorter, _2, _1));
    

     

    bind는 기본적으로 copy를 통해 인자를 함수에 넘겨준다.

    그런데, ostream같은 IO 객체는 copy가 불가능하다. 어떻게 해야할까?

    ref 함수로 해당 객체를 감싸주면 된다.

    #include <ostream>
    #include <iostream>
    #include <functional>
    using namespace std;
    using namespace std::placeholders;
    
    ostream &print(ostream &os, const string &s, char c) {
    	return os << s << c;
    }
    
    int main(){
        ostream& os = cout;
        vector<string> words = {"hello", "bye", "world"};
    
        for_each(words.begin(), words.end(), bind(print, ref(os), _1, ' '));
        return 0;
    }
    

     

    'c++' 카테고리의 다른 글

    C++ Primer CH12. Dynamic Memory  (0) 2024.01.21
    C++ Primer CH11. Associative Containers  (1) 2024.01.21
    C++ Primer CH9. Sequential Containers  (1) 2024.01.21
    C++ Primer CH8. The IO Library  (0) 2024.01.21
    C++ Primer CH7. Classes  (0) 2024.01.21
Designed by Tistory.