C++ 프로그래밍

C++ 람다에서 참조 값과 복사 값 동시에 사용하기

하늘흐늘 2021. 11. 29. 13:22
반응형

C++ 람다는 C++ 특성상 복사와 참조 그리고 객체의 생명주기 등을 고려해야 메모리 관련 버그가 없습니다. 람다에서 참조만 사용할 경우 프로그램에 따라서 참조하는 값이 메모리에서 해제되면 메모리 관련 버그가 발생하게 됩니다. 이럴 경우 복사를 같이 사용해야 합니다.

해당 설명에 대한 아래 예를 살펴보겠습니다. 아래 코드는 해당 상황을 보여주기 위한 예제인 관계로 현실적인 사용과는 조금 다를 수 있으니 참고 바랍니다.

#include <iostream>
#include <string>
#include <functional>

using namespace std;


struct std_15_sub
{
public:
	int value = 1;
};

class std_15A
{
private:
	void print_value(int value)
	{
		cout << value << endl;
	}

public:
	function<void(void)> get(std_15_sub* sub)
	{
		function<void(void)> result = [&]
		{
			print_value(sub->value);
		};

		return result;
	}
};


class std_15B
{
private:
	void print_value(int value)
	{
		cout << value << endl;
	}

public:
	function<void(void)> get(std_15_sub* sub)
	{
		function<void(void)> result = [&, value = sub->value]
		{
			print_value(value);
		};

		return result;
	}
};


int main(int argc, char* argv[])
{
	std_15_sub* sub = new std_15_sub();
	std_15A test1;
	auto func1 = test1.get(sub);
	delete sub;
	func1();

	sub = new std_15_sub();
	std_15B test2;
	auto func2 = test2.get(sub);
	delete sub;
	func2();

	return 0;
}

해당 예제에 대한 결과는 아래와 같습니다.

-572662307
1

기본적으로 위의 예에서 람다는 클래스 함수를 사용하기 때문에 참조를 사용해야 합니다.
위의 예에서 결과를 살펴보면 func1()의 결과는 마이너스로 시작하는 이상한 값이 나왔습니다. 이유는 func1을 실행하는 시점에서 func1에서 참조하는 sub객체가 메모리에서 해제되었기 때문입니다.
func1()과 다르게 func2()에서는 예상 했던 정상적인 값인 1이 나왔습니다. 이유는 func2는 [&, value = sub->value]와 같이 출력하는 값을 value란 새변수에 복사하여 놓았기 때문입니다.

이상 살펴본 봐와 같이 람다 함수에서 사용하는 객체의 값이 메모리에서 해제될 수 있을 때에는 값을 복사하여 놓아야 합니다. 일반적인 경우라면 [=]와 같이 기본을 복사로 지정할 수 있습니다. 하지만 예에서와 같이 기본을 참조로 지정해야 하는 경우에는 [&, value = sub->value]의  value = sub->value와 같이, {새 변수} = {기존 변수 값}와 같이, 값을 복사해서 람다 함수에서 값을 가지고 있어야 합니다.

 

반응형