2012-02-08 25 views
12

GCC dường như nắm bắt sai các biến toàn cầu bằng cách tham chiếu trong các hàm lambda, ngay cả khi chúng được chỉ định là 'capture by value'. Mã này sẽ biên dịch và in "a = 9":GCC nắm bắt sai các biến toàn cầu bằng cách tham chiếu trong các hàm lambda?

#include <iostream> 

int a = 10; 

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

Trong khi mã này sẽ không biên dịch:

#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; 
} 

Nhưng chụp một cách rõ ràng toàn cầu theo giá trị và sau đó gán cho nó cung cấp cho các lỗi:

#include <iostream> 

int a = 10; 

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

Tôi khá chắc chắn rằng lỗi là hành vi chính xác - tại sao việc thu thập tiềm ẩn phá vỡ lỗi này? Tôi chỉ khám phá các tính năng mới của C++ 11 và vô tình viết đoạn mã đầu tiên (không nhận ra nó là một lỗi) và sau đó đã ngạc nhiên khi những sửa đổi đối với những gì tôi cho là một biến cục bộ ảnh hưởng đến toàn cục.

Vì nó phải là lỗi gán cho biến được ghi theo giá trị trong một lambda, GCC có lẽ sử dụng tham chiếu đến biến cho mục đích tối ưu hóa, ít nhất trong trường hợp này và không phát hiện được phép gán sai .

+1

VS2010 cư xử theo cùng một cách trên tất cả các tài khoản. Thật không bình thường khi hai lần triển khai thực hiện lỗi chính xác theo cùng một cách vì vậy tôi nghĩ rằng đây có thể không phải là lỗi. –

+6

Bạn không bắt giữ ở đây - chỉ các biến có lưu trữ tự động mới có thể được chụp (và 'this'). Bạn chỉ đơn giản là sử dụng toàn cầu như một toàn cầu, không có gì đặc biệt về lambdas trong bối cảnh này. – ildjarn

Trả lời

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; ...

biến toàn cục có thời gian lưu trữ tĩnh (§3.7.1), do đó toàn cầu a sẽ không ngầm bắt bởi giá trị. Tuy nhiên, bạn có thể truy cập vào biến toàn cục ở bất kỳ nơi nào, do đó,

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

sẽ đặt toàn cầu a thành 9 như mong đợi.

Rõ ràng chiếm được một thế giới phải là một lỗi hoặc UB, vì §5.1.2/10 nói

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.

Các vấn đề liên quan