프로그래밍 일반/C++ 프로그래밍

[C++] Closure(클로저)

지노윈 2020. 8. 24. 16:48
반응형
Closure?
Lexical binding을 지원하는 함수형 언어로 부터 파생된 개념이며, 코드 블럭을 정의할때 스코프내의 환경들을 기억하여 나중에 수행될 때도 원래의 환경에 따라 수행되는 것을 말합니다.

 

람다 표현식 VS 클로저

스콧 마이어(Scott Meyers)는 "람다와 클로저의 차이는 클래스와 클래스 인스턴스 사이의 차이점과 동일하다"라는 좋은 예를 들었습니다. 클래스는 오직 소스 코드에만 존재하며 런타임에 존재하지 않습니다. 클래스 인스턴스만이 런타임에 존재합니다. 즉, C++에서는 람다 표현식이 인스턴스화 된 것을 클로저라 합니다.


클로저의 예

#include <iostream>
#include <functional>

std::function<void(void)> closureWrapper1()
{
    int x = 10;
    return [x](){std::cout << "Value in the closure: " << x << std::endl;};
}

std::function<void(void)> closureWrapper2()
{
    int x = 10;
    return [&x](){x += 1; std::cout << "Value in the closure: " << x << std::endl;};
}

int main()
{
    int x = 10;
    auto func0 = [&x](){x += 1; std::cout << "Value in the closure: " << x << std::endl;};
    std::function<void(void)> func1 = closureWrapper1();
    std::function<void(void)> func2 = closureWrapper2();
    func0();
    func0();
    func0();
    std::cout << "-------------------------" << std::endl;
    func1();
    func1();
    func1();
    std::cout << "-------------------------" << std::endl;
    func2();
    func2();
    func2();
}

출력 결과입니다.

Value in the closure: 11
Value in the closure: 12
Value in the closure: 13
-------------------------
Value in the closure: 10
Value in the closure: 10
Value in the closure: 10
-------------------------
Value in the closure: 32765
Value in the closure: 32766
Value in the closure: 32767

이 예에서 func1과 func2는 클로저가 아닙니다. 이들은 클로저를 랩핑한 std::function 래퍼 오브젝트 입니다.

func0는 클로저입니다. 그러나 이것은 람도 표현식에 의해 생성된 클로저의 복사본입니다.

 

func0은 main함 스코프에서 x 변수의 참조를 캡쳐했습니다. 그러므로, main 함수의 스코프에서 x값이 1증가합니다.

func1은 closureWrapper1의 스코프에서 x의 값을 캡처했습니다(x 값 복사). 그러므로, x의 값은 항상 10입니다.

func2는 closureWrapper2의 스코프에서 x의 참조를 캡쳐했습니다. 그러나 함수가 리턴된 이후에 로컬 변수 x는 스코프 밖입니다.  

 

참고: https://leimao.github.io/blog/CPP-Closure/