Кажется, GCC неправильно захватывает глобальные переменные по ссылке в лямбда-функциях, даже если они указаны как «захват по значению». Этот код скомпилирует и напечатает «a = 9»:
#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 предположительно использует ссылку на переменную в целях оптимизации, по крайней мере, в этом случае, и не обнаруживает ошибочное присвоение.