在最近的一份 C++0x 草案 (n3225.pdf) 中,我们可以找到 5.1.2/10:
使用非限定名称查找的常用规则来查找捕获列表中的标识符(3.4.1);每个此类查找都应找到在本地 lambda 表达式的到达范围中声明的具有自动存储持续时间的变量。如果一个实体(即变量或 this)出现在 lambda 表达式的捕获列表中,则称该实体已被显式捕获。
That seems对我来说相当限制。例如,它seems对我来说,以下事情是不允许的:
int global;
struct s {
int x;
void memfun() {
[x,global]{};
}
};
since x
不一定是自动存储的变量,也不是global
。请注意,此捕获子句的目的是让 lambda 对象存储一个copy of x
and global
如果它们在稍后阶段发生变化,这可能是可取的。我已经知道一个替代方案:
int global;
struct s {
int x;
void memfun() {
int copyx = x;
int copyglobal = global;
[copyx,copyglobal]{};
}
};
但这归结为额外的副本和额外的样板只是为了捕获x
and global
作为副本。
另外,我在最新的草案中找不到任何关于如果我们在捕获子句中命名本地引用会发生什么的结论:
int main() {
int i = 0;
int &r = i;
assert([r]{return &r;}() != &i);
}
lambda 对象是“复制引用”还是“复制 int”?如果它通过副本捕获引用的对象,这可以为我们节省之前解决方法中的额外副本。
GCC 显然支持所有这些示例,并在最后一种情况下存储 int 的副本(恕我直言,这是可取的)。但我想知道这实际上是否是 C++0x 草案的预期行为,或者只是编译器扩展或实现错误。
Edit:
templatetypedef 指出 5.1.2/14 解释了当在捕获子句中命名引用时会发生什么。据我所知,这允许我们对第一个示例使用以下解决方法:
int global;
struct s {
int x;
void memfun() {
auto& cx = x;
auto& cglob = global;
[cx,cglob]{};
}
};
蒂亚,
塞利比策