C ++ 11 람다는 사용하지 않는 변수를 캡처합니까?


124

를 사용 [=]하여 모든 지역 변수를 람다의 값으로 캡처 하려는 경우 함수의 모든 지역 변수가 복사되거나 람다에서 사용되는 모든 지역 변수 가 생성 됩니까?

예를 들어 다음과 같은 경우

vector<int> my_huge_vector(100000);
int my_measly_int;
some_function([=](int i){ return my_measly_int + i; });

my_huge_vector는 람다에서 사용하지 않아도 복사됩니까?

답변:


115

캡처 목록에 명시 적으로 이름이 지정된 각 변수가 캡처됩니다. 기본 캡처는 (a) 캡처 목록에 명시 적으로 이름이 지정되지 않은 변수와 (b) 람다 식의 본문에 사용되는 변수 만 캡처합니다 . 변수의 이름이 명시 적으로 지정되지 않았고 람다 식에서 변수를 사용하지 않으면 변수가 캡처되지 않습니다. 귀하의 예에서는 my_huge_vector캡처되지 않습니다.

C ++ 11 §5.1.2 [expr.prim.lambda] / 11 기준 :

경우 람다 표현이 연관된있다 캡처 기본 및 그 화합물 문 ODR-사용 this 또는 자동 저장 기간과의 변수 ODR 사용되는 개체를 명시 적으로 포착되지 않습니다, 다음 ODR 사용되는 개체는 암시 적으로 캡처 할 수 있다고합니다.

람다 식에는 연결된 캡처 기본값이 있습니다. 기본적으로 [=].

변수가 사용되는 경우에만 ( "사용"이라는 용어의 단일 정의 규칙 의미에서) 변수가 암시 적으로 캡처됩니다. my_huge_vector람다 식의 본문 ( "복합 문")에서 전혀 사용하지 않기 때문에 암시 적으로 캡처되지 않습니다.

§5.1.2 / 14를 계속하려면

엔티티는 다음과 같은 경우 사본으로 캡처됩니다.

  • 그것은 암시 적으로 포착하고있다 캡처 - 기본=경우 또는
  • 포함되지 않은 캡처로 명시 적으로 캡처됩니다 &.

당신 때문에 my_huge_vectorIS 암시 캡처되지 및 명시 적으로 포착되지 않는, 그것은 사본 또는 참조를 기준으로, 전혀 포착되지 않는다.


10
당신은 거룩한 인용문이 있습니까?
GManNickG

그러나 모든 세부 사항을 이해하려면 §5.1.2의 전체 내용이 중요하다고 말할 것입니다. 이 섹션에는 많은 기술 용어가 정의되어 있으며 람다 식의 다양한 구성 요소에 대한 정의가 반드시 얽혀 있기 때문에 "이것이 X이고 이것이 X 인 이유입니다."라는 짧은 따옴표를 꺼내기가 어렵습니다.
James McNellis

최소한 명시 적으로 명명 된 변수에 대해서는 이러한 최적화가 허용되지 않는다는 의미로 여기 에서 주의를 기울이 십시오 . 어디에 선을 그릴 지 모르겠습니다.
GManNickG 2010 년

@GManNickG : 그것은 강력한 좋은 트롤링입니다 ;-). 실제로이 페이지를 가리키고 있다는 사실을 깨닫기 전에 링크를 세 번 클릭했습니다 ... : -O [어쨌든 내일 아침 사무실에 들어가서 업데이트 할 때 언어 사양을 다시 읽겠습니다. 대답 적절].
제임스 McNellis

오, 미안해 !!! 내 질문에 대한 답변이 있었지만 대신 여기 에 연결하려고했습니다 . 그것은 몹시 혼란 스러웠을 것입니다.
GManNickG

16

아니요, my_huge_vector캡처되지 않습니다. 사용[=]모든 변수가 람다에 캡처 됨을 의미합니다 .


6
네. 참고 사용은 하지만, 기술적 인 단어이며, 정말 하나의 정의 규칙을 의미합니다 사용되는 . 예를 들어 void f() { const int size(10); [] { int x[size]; }; }. 여기서는 size캡처되지 않지만 ODR 의미에서 사용되지 않기 때문에 괜찮습니다. (Visual C ++ 2010은 VC10이 출시 된 후 사양이 변경되었거나 버그로 인해이 코드를 허용하지 않습니다. 아마도이 코드는 향후 버전에서 수정 될 것입니다. g ++ 4.5.1에서 허용합니다.)
James McNellis

@JamesMcNellis dpn 걱정하지 마세요, MSVC는 오늘날에도 여전히 냄새 나는 쓰레기 더미입니다. cf. godbolt.org/z/vHnnCX(lulz의 경우 gcc에서 확인). 그것은 말했다; 평가 된 식에 나타나는 식별자가 ODR을 사용하지 않는 이유를 이해할 수 없습니다. 나는이 경우가 constexpr로 해석 될 수 있다는 의미가 아니라면 분명히 ODR을 사용한다고 생각합니다. 따라서 값 만 유용합니까? 컴파일러가 const물건이 잠재적으로 변형되지 않는다고 가정하는지 잘 모르겠습니다 . 매우 공격적인 최적화 플래그 OX 같은 것이 아니라면.
v.oddou
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.