C++ 픽업 - lambda 표현식 원리

C++ 픽업 - lambda 표현식 원리

전언


lambda 표현식은 C++11의 새로운 표준에서 제시된 것입니다.lambda 표현식에서 우리는 그것의 사용을 집중적으로 정리했다.지금 그것의 실현 원리를 토론해 봅시다.

본문


1. 함수 대상


클래스의 대상은 괄호와 결합하여 함수의 일반적인 행위를 나타내는데 이 대상을 함수 대상이라고 할 수 있다.
#include <iostream>
using namespace std;
class MyClass
{
public:
	// ()
	int operator()(int i)
	{
		return i;
	}
};
int main()
{
	MyClass my;
	//my() 
	int i = my(1);     //  my.operator()(1)
	cout << "i = " << i << endl;
	cin.get();
	return 0;
}

실행
이 예는 함수 대상의 본질이 함수 호출 연산자를 다시 불러온 것을 설명한다.하나의 클래스가 함수 호출 연산자 ()를 다시 불러오면 그 대상은 함수 대상이 된다.이것은 lambda 표현식 내부의 실현을 이해하는 기초이다.

2. lambda 표현식 원리


원리: 컴파일러는 lambda 표현식을 익명 클래스의 익명 대상으로 만들고 클래스에서 함수를 다시 불러와 연산자를 호출합니다.
우리 는 가장 간단한 lambda 표현식 에서 착안하여, 쉬운 것 부터 어려운 것 까지

2.1 캡처 목록 및 매개변수 목록 없음

auto print = []{cout << "zhangxiang" << endl; };

컴파일러는 이 문장을 다음과 같은 상황으로 번역할 것이다.
// lambda 
class print_class
{
public:
	void operator()(void) const
	{
		cout << "zhangxiang" << endl;
	}
};
// ,print 
auto print = print_class();

클래스를 생성하는 클래스 이름 규칙은 다변적일 수 있습니다. 꼭 그렇지는 않습니다.

2.2 캡처 목록은 없지만 매개 변수 목록이 있음

auto add = [](int a, int b){return a + b; };

컴파일러는 이 문장을 다음과 같은 상황으로 번역할 것이다.
class add_class
{
public:
	auto operator()(int a, int b) const
	{
		return a + b;
	}
};
auto add = add_class();

2.3 캡처 목록, 매개변수 목록 옵션


포획 방식은 두 가지로 나뉘는데 그것이 바로 인용포획, 값포획이기 때문에 이런 상황에서 세분화할 수 있다.

2.3.1 값 캡처

int year = 19900212;
char *name = "zhangxiang";
// , , year,name
auto print = [=](){
	cout << year << ends << name << endl;
};

번역하다
int year = 19900212;
char *name = "zhangxiang";
class print_class
{
public:
	// 
	print_class(int year, char *name) :year(year), name(name)
	{

	}
	void operator()(void) const
	{
		cout << year << ends << name << endl;
	}
private:
	int year;
	char *name;
};
auto print = print_class(a, str);

운행 효과가 같으니 시범을 보이지 않겠다.

2.3.2 참조 캡처

int year = 19900212;
char *name = "zhangxiang";
auto print = [&](){
	year++;
	cout << year << ends << name << endl;
};

번역하다
int year = 19900212;
char *name = "zhangxiang";
class print_class
{
public:
	// , 
	print_class(int &year, char *&name) :year(year), name(name)
	{

	}
	void operator()(void) const
	{	
		year++;   // ,const 
		cout << year << ends << name << endl;
	}
private:
	int &year;
	char *&name;
};

테스트를 통해 효과도 마찬가지다.

2.3.3 블렌드 캡처

int year = 19900212;
int shoes = 42;
char *name = "zhangxiang";
auto show = [&, shoes]()mutable{
	shoes++;
	year++;
	cout << year << ends << shoes << ends << name << endl;
};

번역하다
int year = 19900212;
int shoes = 42;
char *name = "zhangxiang";
class show_class
{
private:
	int &year;
	mutable int shoes;
	char *&name;
public:
	show_class(int &year, int shoes, char *&name) :year(year), shoes(shoes), name(name)
	{

	}
	void operator()(void)const
	{
		shoes++;
		year++;
		cout << year << ends << shoes << ends << name << endl;
	}
};
auto show = show_class(year, shoes, name);
show();

기본적으로 값을 통해 포획된 변수는 파라미터 목록 뒤에 키워드mutable을 추가하지 않으면 수정할 수 없습니다.상기 코드는 클래스에 대응하는mutable가 어떻게 추가되었는지 보여 줍니다.물론 lambda 표현식에 mutable를 추가하면 함수를 다시 불러올 때 const 수식을 하지 않는 또 다른 실현 방법도 있다.

총결산


이상의 예시 코드는 기본적으로 각종 상황의 lambda 표현식의 실현 원리를 모두 보여 주었기 때문에 자세히 생각해 보면 매우 쉽다.
본 칼럼 목록
  • C++ 픽업 디렉토리
  • 모든 내용의 디렉터리
  • CCPP Blog 디렉토리
  • 좋은 웹페이지 즐겨찾기