본문으로 바로가기

3주차 강의내용 정리

category C++/여담 2019. 3. 24. 13:17




shared_ptr

unique_ptr


전에 smart pointer 에 대한 글을 작성한 적이 있다. 읽기 바람


https://openmynotepad.tistory.com/33?category=853099


추가로 auto_ptr 은 더 이상 지원이 되지 않는다.


std::transform


std::transform 은 입력 이터레이터의 처음과 끝, 그리고 변경된 요소를 새로 붙혀넣을 출력 이터레이터의 처음, 그리고 함수 객체를 받는다.


1
2
3
template< class InputIt, class OutputIt, class UnaryOperation >
OutputIt transform( InputIt first1, InputIt last1, OutputIt d_first,
                    UnaryOperation unary_op );
cs


1
2
3
template< class InputIt, class OutputIt, class UnaryOperation >
constexpr OutputIt transform( InputIt first1, InputIt last1, OutputIt d_first,
                              UnaryOperation unary_op );
cs


https://en.cppreference.com/w/cpp/algorithm/transform

C++17 에서 많은 STL algorithm library 의 policy 가 변경되면서, 생성자에 많은 변화가 생겼다. 한번 쯤 읽어봐도 좋음!


1. std::transform 이 단항 펑크터 ( 단항 술어 ) 를 받을 때 


1
2
3
4
5
6
7
8
9
template<class InputIt, class OutputIt, class UnaryOperation>
OutputIt transform(InputIt first1, InputIt last1, OutputIt d_first, 
                   UnaryOperation unary_op)
{
    while (first1 != last1) {
        *d_first++ = unary_op(*first1++);
    }
    return d_first;
}
cs

2. std::transform 이 이항 펑크터 ( 이항 술어 ) 를 받을 때


1
2
3
4
5
6
7
8
9
10
template<class InputIt1, class InputIt2, 
         class OutputIt, class BinaryOperation>
OutputIt transform(InputIt1 first1, InputIt1 last1, InputIt2 first2, 
                   OutputIt d_first, BinaryOperation binary_op)
{
    while (first1 != last1) {
        *d_first++ = binary_op(*first1++*first2++);
    }
    return d_first;
}
cs


std::transform 은 술어로 '변경 된' 값을 반환한다. 
for_each 는 작업의 반환값을 무시한다.

1
2
3
4
5
6
7
8
9
    std::string a[5]{ "C++""abab""aeiou""AEIOU""Fighting!" };
    transform(begin(a), end(a), ostream_iterator<std::string>(cout"\n"), [](std::string lhs){
        for (auto i = lhs.begin(); i != lhs.end(); ++i) {
            if (*== 'a' || *== 'e' || *== 'i' || *== 'o' || *== 'u')
                *= '*';
        }
        return lhs;
    });
    // C++, *b*b, *****, AEIOU, F*ght*ng!
cs

1
2
3
4
5
6
7
8
9
    for_each(begin(a), end(a), [](std::string lhs) {
        for (auto i = lhs.begin(); i != lhs.end(); ++i) {
            if (*== 'a' || *== 'e' || *== 'i' || *== 'o' || *== 'u')
                *= '*';
        }
        return lhs;
    });
    for (auto i : a)
        cout << i << endl// C++, abab, aeiou, AEIOU, Fighting
cs

사실은 이게 std::transform 과 std::for_each 의 차이라고 할 수 있는데,. std::for_each 는 함수 객체가 뭘 반환하든 다 무시해버린다.
그에 반해 std::transform 은 함수 객체의 반환값을 변경한다. ( 진짜다, std::string a 의 값도 변경돼있다! )
std::transform 은 돌연변이 알고리즘이라고도 부르며, 순차적을 보증하지 않는 각 iterator 를 만나며 그 값을 변경 한다.
하지만 for_each 는 순차적을 보장하며, 원본 값을 변경하지 않는다. ( 물론 반환값에 한정해서 말이다. 저기 람다의 인자가 std::string& 가 되면 값은 변경 된다.. )

물론 for_each 도 요즈음에는 잘 쓰이지 않는다. 왜냐면 for range loop 가 있기 때문에.
이번 C++17에 for_each_n 이 등장했다. ? index 에서 n 번 떨어진 index 까지 작동시킬 수 있는데, 이로 인해
무조건 전체를 순회해야했던 for_each 와 for range loop 의 문제점을 해소할 수 있게 되었다.