Modern C++ - lambda) 복습을 위해 작성하는 글 2023-11-16

rizz·2023년 11월 16일
0

Modern C++

목록 보기
3/3

📒 C++ - lambda

📌 lambda란?

- 익명 함수 객체를 편리하게 정의할 수 있다.

- 알고리즘 또는 비동기 함수에 전달되는 코드를 캡슐화하는 데에 사용된다.

 

📌 lambda의 형태

	[capture](return type)
		{
			source code
		}();

capture : 람다 스코프 외부에서 어떠한 변수를 가져오는 것.

 

// C++
#include <iostream>

int main()
{
	int value = 10;
	auto func = [value]()
		{
			value = 20; // 에러
		};
}

- 캡처된 변수를 수정하게 되면 함수를 실행할 때마다 결괏값이 변경되기 때문에 기본값이 const이다.

- 참조로 받게 되면 값은 변경이 가능하다. 왜냐하면 캡처의 주소를 바꾸는 것이 아니라 값만 바꾸는 것은 함수 객체에 변함은 없기 때문이다.

- mutable 키워드를 활용하여 값을 변경할 수 있다.

// C++
#include <iostream>

int main()
{
	int value = 10;
	auto func = [value]() mutable
		{
			value = 20;
			std::cout << value << std::endl;
		};
	std::cout << value << std::endl;
	func(); // 호출
}

Output:
20
10

mutable : const 함수에서 멤버 변수의 값을 수정할 수 있게 한다.

 

📌 capture

	int num0 = 10;
    int num1 = 20;
    
    auto func = [=] () // 모든 캡처를 값으로.
    {
    	reutrn num0 + num1;
	};
    
        auto func = [&] () // 모든 캡처를 레퍼런스로.
    {
    	reutrn num0 + num1;
	};
    
    auto func = [&, num0]() // num0은 값, 나머지는 레퍼런스.
	{
		return num0 + num1;
	};
    
        auto func = [=, &num0]() // 나머지는 값, num0은 레퍼런스.
	{
		return num0 + num1;
	};

 

// C++
#include <iostream>

auto func()
{
	int num = 10;
	return [&]
		{
			return num;
		};
}


int main()
{
	auto f = func();
	std::cout << f() << std::endl;
}

- 값이 제대로 제대로 나올 수도 있고, 안 나올 수도 있다.

- 레퍼런스로 캡쳐하면 자동 지역변수이기 때문에 스택에서 사라질 수 있다.

 

// C++
#include <iostream>

struct Test
{
	int num = 10;
	auto func()
	{
		return [=]
			{
				return num;
			};
	}
};

int main()
{
	Test* t = new Test;
	auto func = t->func();
	delete t;

	std::cout << func() << std::endl;
}

Output:
-572662307 // 쓰레깃값 출력.

- 값으로 캡쳐된 것처럼 보이지만, 사실상 this가 캡처된 것이다.

- 아래 예시로 해결할 수 있다.

// C++
#include <iostream>

struct Test
{
	int num = 10;
    
	auto func()
	{
		return [num = num] // initialize capture
			{
				return num;
			};
	}
};

int main()
{
	Test* t = new Test;
    auto func = t->func();
    delete t;
    
    std::cout << func() << std::endl;
}

- initialize capture를 활용하면 값으로 캡처할 수 있다.

- C++14 이상에서 사용할 수 있다.

- C++11이라면 func() 함수 안에서 temp 변수를 따로 만들어서 넘겨주어야 한다.

- *this를 활용할 수도 있지만 this 전체가 복사되는 것이기 때문에 바람직하지 않아 보인다.

 

📌 Generic lambda(C++14 이상)

// C++
#include <iostream>

int main()
{
	auto func = [](auto value)
	{
		return value;
	};

	std::cout << func(10) << std::endl;
	std::cout << func("A") << std::endl;
	//std::cout << func({ 1,2,3 }) << std::endl; // initiallize list는 불가.
}

Output:
10
A

- auto이기 때문에 initiallize list는 불가능하다.

 

📌 Generic lambda(C++20 이상)

// C++
#include <iostream>

int main()
{
	auto func = []<typename T>(T value)
	{
		return value;
	};

	std::cout << func(10) << std::endl;
	std::cout << func("10") << std::endl;
}

Output:
10
A
profile
복습하기 위해 쓰는 글

0개의 댓글