2012-02-08 5 views
12

GCC는 '값으로 캡처'로 지정되어 있어도 람다 함수에서 참조로 전역 변수를 잘못 캡처하는 것으로 보입니다. 이 코드는 컴파일 및 인쇄 "는 = 9"됩니다GCC가 람다 함수에서 참조로 전역 변수를 잘못 캡처합니까?

#include <iostream> 

int a = 10; 

int main() 
{ 
    [=]() { a = 9; }(); 
    std::cout << "a = " << a << std::endl; 
    return 0; 
} 

이 코드는 컴파일되지 않습니다 동안 :

#include <iostream> 

int main() 
{ 
    int a = 10; 
    [=]() { a = 9; }(); // error: assignment of member 'main()::<lambda()>::a' in read-only object 
    std::cout << "a = " << a << std::endl; 
    return 0; 
} 

을하지만, 명시 적으로 할당 한 후 값으로 세계를 캡처하고 오류를 제공합니다

#include <iostream> 

int a = 10; 

int main() 
{ 
    [a]() { a = 9; }(); // assigment of read-only object 
    std::cout << "a = " << a << std::endl; 
    return 0; 
} 

저는 오류가 올바른 동작임을 확신합니다. 왜 암시 적 캡처가이 오류를 우회합니까? 나는 새로운 C++ 11 기능을 탐색하고 실수로 코드의 첫 번째 부분을 썼다. (오류가 발생하지 않는다는 사실을 깨닫지 못함) 로컬 변수가 전역에 영향을 미쳤다 고 가정했을 때 수정 된 사항에 놀랐다.

람다에서 값으로 캡처 한 변수에 할당하는 것이 오류가되어야하므로 GCC는 최적화를 위해 변수에 대한 참조를 사용합니다 (적어도이 경우에는). 잘못된 할당을 감지하지 못합니다 .

+1

VS2010는 모든 계정에 동일한 방식으로 동작 말한다 때문에

명시 적으로 글로벌 오류 또는 UB해야 캡처. 두 가지 구현이 정확히 같은 방식으로 버그가있는 것은 드문 일이므로 버그가 아닐 수도 있습니다. –

+6

여기에서는 전혀 캡처하지 않고 있습니다 - 자동 스토리지가있는 변수 만 캡처 할 수 있습니다 (및'this'). 당신은 글로벌을 글로벌로 사용하고 있습니다.이 맥락에서 람다에 관해 특별한 것은 없습니다. – ildjarn

답변

24

§5.1.2/11 :

If a *lambda-expression(has an associated capture-default and its compound-statement odr-uses (3.2) this or a variable with automatic storage duration and the odr-used entity is not explicitly captured, then the odr-used entity is said to be implicitly captured; ...

전역 변수 (§3.7.1) 정적 저장 기간이 있으므로 글로벌 a 내재적 값 캡처 없습니다. 그러나 예상대로 그렇게

[=]() { a = 9; }(); 

9에 글로벌 a을 설정합니다 어디서나 전역 변수에 액세스 할 수 있습니다. §5.1.2/10

The identifiers in a capture-list are looked up using the usual rules for unqualified name lookup (3.4.1); each such lookup shall find a variable with automatic storage duration declared in the reaching scope of the local lambda expression.

관련 문제