В одном из последних проектов C ++ 0x (n3225.pdf) мы можем найти 5.1.2 / 10:
Идентификаторы в списке захвата ищутся с использованием обычных правил для поиска безоговорочного имени (3.4.1); каждый такой поиск должен найти переменную с автоматической продолжительностью хранения, объявленной в области охвата локального лямбда-выражения. Сущность (то есть переменная или эта) называется явно захваченной, если она появляется в списке захвата лямбда-выражения.
Это кажется довольно ограничительным для меня. Например, мне кажется , что запрещены следующие вещи:
int global;
struct s {
int x;
void memfun() {
[x,global]{};
}
};
, поскольку x
не обязательно является переменной с автоматическим хранением и не является global
. Обратите внимание, что цель этого предложения захвата состоит в том, чтобы позволить лямбда-объекту хранить копию из x
и global
, что может быть желательно в случае их изменения на более поздней стадии. Я уже знаю об альтернативе:
int global;
struct s {
int x;
void memfun() {
int copyx = x;
int copyglobal = global;
[copyx,copyglobal]{};
}
};
Но это сводится к дополнительным копиям и дополнительной плите котла, чтобы захватить x
и global
в качестве копии.
Кроме того, я не могу найти ничего убедительного в последних черновиках о том, что произойдет, если мы назовем локальную ссылку в предложении захвата:
int main() {
int i = 0;
int &r = i;
assert([r]{return &r;}() != &i);
}
Лямбда-объект "копирует ссылку" или "копирует int"? Если он захватывает указанный объект путем копирования, это может сэкономить нам дополнительные копии из предыдущего обходного пути.
GCC, очевидно, поддерживает все эти примеры и хранит копию int в последнем случае (что желательно, IMHO). Но я хотел бы знать, является ли это на самом деле предполагаемым поведением в соответствии с черновиками C ++ 0x или просто расширением компилятора соответственно ошибкой реализации.
Edit:
templatetypedef указал на 5.1.2 / 14, который объясняет, что происходит, когда ссылка упоминается в предложении захвата. Насколько я могу судить, это позволяет нам использовать следующий обходной путь для первого примера:
int global;
struct s {
int x;
void memfun() {
auto& cx = x;
auto& cglob = global;
[cx,cglob]{};
}
};
Тиа,
sellibitze