다음 예제를 살펴보겠습니다.
#include <cstdlib>
int main() {
const int m = 42;
[] { m; }(); // OK
const int n = std::rand();
[] { n; }(); // error: 'n' is not captured
}
해야 하는 이유는 무엇입니까 캡처n
에서 두 번째로 람다 하지만m
처음에는 람다? 체크 섹션 5.1.2(Lambda expressions)에서는 C++14 표준만을 찾을 수 없습니다. 할 수 있습니점을 단락에서는 이 설명되어 있나요?
업데이트:저는 이 문제 모두 GCC6.3.1 7(트렁크). 소 4.0 5(트렁크)이 실패하는 오류가 두 경우 모두에서(변'm'할 수 없는 암시적으로 캡처에는 람다와 함께 아니 캡처 기본 지정한
).
을 위한 람다에서 블록 범위 변수 회의 특정 기준에 도달 범위*에 사용할 수 있는 제한적인 방법으로 내부에는 람다,심지 않은 경우에 캡처합니다.
쉽게 말해서,도달 범위을 포함한 모든 변수 지역을 포함하는 함수는 람다는 것에서는 범위에서점 lambda 정의되었다. 그래서 이것을 포함그리고
n`위의 예입니다.
"특정 기준에 기"와"제한적인 방법으로"특히로(C++14):
내부에는 람다,변수가 있지 않아야 합odr-사용는지를 받아야 어떤 작업을 제외하고:
으로 나타나는 버려진 값 표현(m;
중 하나 이러한),또는
는 그것의 값을 검색합니다.
변수이어야 합니다:
Aconst
비휘발성
정수 또는 열거의 이니셜라이저였표현,또는
Aconstexpr 을 사용하여
,non-`휘발성 변수(또는 하위 그러 개)
를 참조하여 C++14:[expr.const]/2.7,[기본입니다.def.odr]/3(첫번째 문장),[expr.prim.람다]/12,[expr.prim.람다]/10.
에 대한 근거는 이러한 규정에 의해 제안으로 다른 코멘트/답변,는 컴파일러가 필요할 수 있"합성"no-capture lambda 으로 자유로운 기능의 독립적인 차단기 때문에(같은 것을 변환할 수 있는 포인터 기능);그것을 할 수 있습에도 불구하고 이것을 참조하여 변수는 경우는 변수는 항상 동일한 값이거나 그것을 반복할 수 있는 절차를 얻기 위해 변's 값의 독립적이 있다. 하지만 그것을 할 수 있't 이는 경우는 변수에서 다 수 있습 시간에 시간 경우,또는 변수는's 주소가 필요한은 예입니다.
에서 코드의n
었으로 초기화한이 일정하지 않음을 표현이다. 따라서n
에 사용할 수 없습니다 lambda 되지 않고 캡처합니다.
m
초기화한 식42
,그래서 그것을 만나면"특정 기준에 기". 폐기-값은 표현하지 않습 odr-를 사용하여 표현,그렇게m;
없이 사용할 수 있습니다m
되고 캡처합니다. gcc 가 올바른 것입니다.
내가 말할 것 둘 사이의 차이를 컴파일러는 그 소리를 고려m;
을 odr-사용전`,하지만 gcc 하지 않습니다. 첫 번째 문장의[기본입니다.def.odr]/3 하는 것은 매우 복잡:
변수는
x
누구의 이름으로 나타 잠재적으로 평가 식ex
은odr-사용의ex
지 않는 한 적용 lvalue-to-번씩만 전환하는x
수익률이 일정하지 않은 식 호출이 아닌 사소한 기능을 경우,x
은 개체ex
의 요소 세트의 잠재적인 결과의 식e
디 lvalue-to-번씩만 변환이 적용된e
,또는e
은 폐기-값은 표현입니다.
하지만 읽기에 바싹 그것은 특별히 언급하는 폐기-값은 표현하지 않odr-는를 사용하는 표현이다.
C++11's 버전[기본입니다.def.odr]원래는 포함하지 않았 폐기 값 식 경우,그래서 그 소's 행동은 올바른 것에서 게시된 C++11. 그러나 표시되는 텍스트에서는 C++14 으로 받아들여졌 결함에 대하여 C++11(문제 712),그렇게 컴파일러를 업데이트해야 자신의 행동은 심지어는 C++에서 11 모니다.
그 때문에 그것을 일정한 표현,컴파일러는 경우[] { 42; }();
이 규칙에[expr.prim.lambda]입니다:
면 람다-식 또는 인스턴스화 함수 호출의 템플릿자의 일반적인 lambda odr-사용(3.2)이나 변하기 쉬운 자동 저장 기간을에서 도달 범위 는 엔티티 것에 의해 캡처 lambda-식입니다.
여기에서 견적 표준[기본입니다.def.odr]:
A x 변수 이름 타 잠재적으로 평가 식 ex odr-하지 않으면 사용 을 적용하 lvalue-to-번씩만 변환 x 산출에는 일정한 표정(...)또는 전자는 폐기됩-값은 표현입니다.
(제거되지 않도록 중요한 부분을 유지 짧)
나의 간단한 이해가:컴파일러 알고 있는는
일정에 컴파일 시간 반면,n
이 변화에 실시 및 따라서n
을 캡처 할 수 있습니다.n
것 odr-사용하기 때문에 당신은 실제로 살펴 안에 무엇을n
를 수행할 필요는 없습니다. 에 다른 단어는 사실이"하나만 있을 수 있습니다"의 정의n
관련이 있습니다.
이에 코멘트에 의해 M.M:
m 은 일정한 표현이기 때문에 그것이's const 자동 변수 상수 이니셜라이저는 식지만,n 지 않은 일정 식기 때문에 그것의 이니셜라이저는 없었던 일정현. 이 에 덮여[expr.const]/2.7. 지속적인 표현입니지 ODR 사용에 따르면,첫번째 문장의[기본입니다.def.odr]/3
여기에 참조에 대한demo.
편집:이전 버전의 대답을 잘못했다. 초보자는's 이 올바른지,여기에 관련 표준을 인용:
- 변 x 누구의 이름으로 나타 잠재적으로 평가 식 exodr-사용여 전지를 적용lvalue-to-번씩만변환하 x 생성상수 식하지 않는 호출이 아닌 사소한 기능을 경우,x 개체 ex 의 요소 세트의 잠재적인 결과의 식 e,어디 하나 lvalue-to-번씩만 전환이 적용되는 전자,또는 전자는 폐기됩-값은 표현입니다. ...
이후m
일정한 표정,그것은 odr 사용하고 있으므로 필요하지 않습 캡처 할 수 있습니다.
표시스템 종소리는 행동하지 않을 준수 표준입니다.