>백엔드 개발 >C++ >C 11 Lambdas는 정의되지 않은 동작을 호출하지 않고도 참조를 캡처할 수 있습니까?

C 11 Lambdas는 정의되지 않은 동작을 호출하지 않고도 참조를 캡처할 수 있습니까?

Susan Sarandon
Susan Sarandon원래의
2024-11-04 22:03:02670검색

Can C  11 Lambdas Capture References Without Invoking Undefined Behavior?

C 11 람다에서 참조 캡처

C에서 람다 표현식은 바깥쪽 범위에서 변수를 캡처할 수 있습니다. 그러나 캡처 방법에 따라 변수에 참조로 액세스할지 아니면 값으로 액세스할지가 결정됩니다. 다음 코드를 고려하세요.

<code class="cpp">#include <functional>
#include <iostream>

std::function<void()> make_function(int& x) {
    return [&]{ std::cout << x << std::endl; };
}

int main() {
    int i = 3;
    auto f = make_function(i);
    i = 5;
    f();
}</code>

이 코드는 [&] 구문을 사용하여 변수 x를 참조로 캡처합니다. 이 프로그램이 정의되지 않은 동작을 호출하지 않고 5를 출력하도록 보장하는지 여부에 대한 의문이 생깁니다.

답변: 예

코드가 올바르게 작동하는 것이 보장됩니다. 기본 표준 표현을 검토하기 전에 이 코드가 C 위원회에서 의도한 대로 작동한다는 점에 유의하는 것이 중요합니다. 그러나 이 문제에 대한 C 11 표준의 초기 문구가 명확하지 않아 설명을 제공하기 위해 CWG 문제 2011이 제기되었습니다. 이 문제는 진행 중인 C 표준 개발에서 해결되고 있습니다.

표준 설명

C 표준의 [expr.prim.lambda]/17에 따르면, 복사로 캡처된 엔터티를 참조하는 ID 표현식만 람다 클로저 유형의 멤버 액세스로 변환됩니다. 참조에 의해 캡처된 엔터티를 참조하는 id-표현식은 단독으로 남겨져 포함 범위에 표시했을 것과 동일한 엔터티를 계속 나타냅니다.

위 코드에서 캡처된 엔터티는 make_function 함수의 매개변수 x입니다. , 이는 람다의 도달 범위에 속합니다. 따라서 람다 식의 참조 x는 기본 함수에 선언된 원래 변수를 참조합니다.

make_function 함수가 반환된 후 x가 수명을 벗어나 참조되는 것이 처음에는 문제가 있는 것처럼 보일 수 있습니다. 그러나 참조가 해당 수명 밖에서 참조될 수 있는 제한된 시나리오가 있습니다. 일반적으로 참조는 범위 내에서 선언되거나 클래스 멤버입니다. 이 경우 클래스 자체는 수명 내에 있어야 합니다.

따라서 표준에서는 수명 이외의 참조 사용을 명시적으로 금지하지 않습니다. 이 허점을 통해 람다 식의 참조를 지원하도록 캡처할 수 있었습니다.

CWG Issue 2012 및 향후 설명

CWG Issue 2012는 이러한 감독을 해결하기 위해 제기되었습니다. 특정 상황에서는 참조가 수명이 끝나도 참조될 수 있습니다. 이 문제의 해결은 참조 참조에 의한 람다 캡처 사양에 의도치 않게 영향을 미쳤습니다. 하지만 이 회귀 문제는 C 17이 출시되기 전에 수정될 것으로 예상됩니다.

위 내용은 C 11 Lambdas는 정의되지 않은 동작을 호출하지 않고도 참조를 캡처할 수 있습니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.