В одном из недавних черновиков С++ 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
в качестве копии.
Кроме того, я не могу найти ничего убедительного в последних черновиках о том, что произойдет, если мы назовем локальную ссылку в предложении capture:
int main() {
int i = 0;
int &r = i;
assert([r]{return &r;}() != &i);
}
Является ли лямбда-объект "копировать ссылку" или "копировать int"? Если он захватывает выделенный объект путем копирования, это может сэкономить нам дополнительные копии из предыдущего обхода.
GCC, очевидно, поддерживает все эти примеры и сохраняет копию int в последнем случае (что желательно, IMHO). Но я хотел бы знать, является ли это на самом деле предполагаемым поведением в соответствии с черновиками С++ 0x или просто с расширением-компилятором относительно ошибки реализации.
Edit:
templatetypedef указал 5.1.2/14, в котором объясняется, что происходит, когда ссылка упоминается в предложении capture. Насколько я могу судить, это позволяет использовать следующий пример для первого примера:
int global;
struct s {
int x;
void memfun() {
auto& cx = x;
auto& cglob = global;
[cx,cglob]{};
}
};
Тиа, sellibitze