posted by REDFORCE 2017. 3. 23. 07:43

목차


1. Auto

2. range based for

3. enum class

4. non-static data member initializers

5. initializer lists

6. default / delete definition

7. override / final

8. emplacement

9. constexpr

10. lambda

11. random

12. thread


와...드디어 10편까지 왔네요. 이틀 동안 열심히 적었습니다만


솔직히 많이 부족하고 너무 설명이 빈약하고 그냥 이런식으로 하면되!


라는 어조로 적어버린 것 같아 죄송합니다.



계속 노력해서 더 좋은 설명을 곁들이도록 할게요!



2. lambda


이번 글은 lambda에 대해서 정리해보도록 하겠습니다.


람다에 대해서 간단히 설명하자면 다음과 같습니다.


  • 'lambda 함수' 또는 '무명 함수' 라고 부르기도 한다.
  • lambda는 함수 오브젝트 이다.
  • C++의 표현력을 증가시켜 준다.
  • STL의 알고리즘을 더 간편하게 사용할 수 있다.
  • 규격에서는 lambda는 특별한 타입을 가지고 있다고 한다.
  • 단! decltype나 sizeof 에서 사용 할 수 없다.


람다의 사용 방법은 4가지만 잘 익혀두시면 됩니다.



위에서 차례대로 설명드리겠습니다.


먼저 어떤 스코프의 영역에서 람다를 쓰실려면    [ ] 를 이용하여 람다를 캡쳐~! 합니다.


그러면 컴파일러가 어? 람다 쓰넴. 하고 알게됩니다.



그 다음 이용할 ( ) 를 통해 파라미터 인수를 정의합니다.

(만약 딱히 파라미터 받을 거 없는데? 하면 안써도 됩니다)


그리고 { } 안에서 함수의 본체를 정의합니다.


마지막으로 ( ) 를 통해 우리가 만든 람다 함수를 호출하면 끝!



간단하게 위와 같이 사용하시면 됩니다.

(역시나 파라미터 없는데~? 하면 안써도 무방합니다)



그리고 람다 함수본체까지만 정의하고 auto를 이용해 함수를 auto func 에 담아둔 뒤


func( )를 이용한 호출도 가능합니다!


왜??  위에서 언급했다싶이 Lambda 또한 함수 오브젝트! 이기 때문이지요!



그리고 람다 자체를 함수의 파라미터로 이용할 수 있습니다.




람다 자체의 파라미터를 사용해보는 것도 확인해볼까요.



역시나 쉽습니다.


그냥 파라미터 값도 알아서 척척 넣어주게 되네요.




그 다음 lambda를 이용한 반환(리턴)을 써보겠습니다.



반환하는 방식도 여타 함수와 똑같습니다. 그냥 함수 본체에다 리턴만 알아서 하면되네요.




그럼 이 람다를 응용해서 함수안에 람다 함수를 넣어서 써보도록 하조



네...잘들어갑니다 ㅡ_ ㅡ)...그냥 함수나 어떤 스코프범위 안에서 


그냥  [ ] 캡쳐를 이용해서 선언만 하면 어디서든 람다를 바로바로 넣을 수 있습니다.



그리고 lambda 함수 자체를 반환하는 함수로 만들어 사용도 가능합니다.




그런데 개인적으로 이런식으로 쓰고 싶지는 않네요...


함수 포인터를 써야하는 과정에서 람다를 이용해 어딘가에 템플릿 형태로 만들어놓고 그걸 리턴 하는 용도로 쓴다면


나름 괜찮을 것 같습니다.



자 그런데..위 코드에 보면 [ ] (캡쳐) 부분에 [=] 이런식으로 들어간 게 보일 겁니다!


응? 못보던건데 저게 뭐지 할텐데요.



Capture 라 불리는 [ ] 구역의 용도는 정확히 


lambda를 정의한 scope 내의 변수를 capture 하는 용도입니다!


Scope의 모든 변수를 참조로 capture 할 때는 [&], 특정 변수를 참조로 capture 할 때는 [&변수]

Scope의 모든 변수를 복사로 capture 할 때는 [=], 특정 변수를 복사로 capture 할 때는 [변수]


를 적으면 됩니다!  ( 무슨말?? )


바로 한번 써보도록 할까요.




위와 같이 람다 함수내에서 지금 스코프의 영역에 있는 변수를 참조하여 값을 변경하거나 할 때는 [&]를 이용해 x 값을 받아 올 수 있습니다.



그럼 [=]를 이용한 복사는?



당연히 값 복사만 일어나기 때문에 스코프내의 변수를 바꿔버리는 행위는 에러를 뿜게 됩니다.


순전히 값 복사와 람수 함수 내부적으로 일어나는 변환에 대해서만 처리를 할 수 있습니다.



그러나 필요하다면 


mutable을 이용하여 다음과 같이 람다 함수 내에서만 일시적으로 x 값을 변경 할 수 있습니다.




람다 함수를 빠져나오면 다시 x 값은 원래 값으로 보존이 됩니다.



다음은 람다의 capture : default 에 대해서 보도록 하겠습니다. 

capture : default 라는 말은 우리가 람다를 씀에 있어서


capture가 어떻게 돌아가는지 본다는 뜻 입니다.



위와 같이 람다의 캡쳐 내에서 설정을 어떻게 하냐에 따라 스코프영역의 변수들의 참조/복사를 할 수 있습니다.



람다에 대한 특징을 정리해보겠습니다.


클래스에서 lambda 사용

  • 클래스의 멤버 함수에서 lambda 사용 가능
  • public, protected, private 멤버도 접근 가능
  • lambda는 클래스에서 friend로 인식
  • lambda에서 클래스 멤버를 호출 할 때는 this를 사용한다.


Generic lambdas

  • C++ 14
  • 인수 타입으로 auto를 사용할 수 있다.
  • 템플릿 인수와 같이 형 추론된다.
  • [ ] (const auto& x, const auto& y) { return x + y; }

  • 가변 인수로 사용 할 수 있다.
  • [ ] ( auto&&... args) { std::cout << sizeof...(args) << endl; } (1U, 2.1, nullptr, hoge{ } );

  • auto를 사용하는 것은 구현에서 필수는 아니다.
    다만 가독성을 위해 붙여주도록 하자!

마지막으로 generic lambda 사용을 보도록 하겠습니다.





여기까지가 C++ 14의 람다 였습니다.


람다에 대한것은 잘 사용하면 정말 편하고 코드를 간결하게 만들 수도 있으며

알고리즘을 구현하는데 있어서 많은 도움이 될 거라 봅니다.


저도 아직은 자주 쓰는 편은 아니지만


일부 구역에서는 람다를 이용해서 굳이 필요없는 펑션 구현을 줄일 수 있다는 점에서는 애용하고 있습니다.



많은 도움이 되셨기를....


혹시나 보셨다면 리플이라도...(굽신 굽신)