【发布时间】:2011-07-25 02:51:35
【问题描述】:
在最近的一份 C++0x 草案 (n3225.pdf) 中,我们可以找到 5.1.2/10:
使用非限定名称查找 (3.4.1) 的常用规则查找捕获列表中的标识符;每个这样的查找都应该找到一个在本地 lambda 表达式的到达范围内声明的具有自动存储持续时间的变量。如果实体(即变量或 this)出现在 lambda 表达式的捕获列表中,则称其被显式捕获。
这似乎对我来说相当限制。例如,在我看来,似乎以下事情是不允许的:
int global;
struct s {
int x;
void memfun() {
[x,global]{};
}
};
因为x 不一定是具有自动存储功能的变量,global 也不一定。请注意,此捕获子句的目的是让 lambda 对象存储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);
}
lambda 对象是“复制引用”还是“复制 int”?如果它通过副本捕获引用的对象,这可以为我们节省先前解决方法中的额外副本。
GCC 显然支持所有这些示例,并在最后一种情况下存储 int 的副本(这是可取的,恕我直言)。但我想知道这实际上是根据 C++0x 草案的预期行为,还是只是编译器扩展,分别是实现错误。
编辑:
templatetypedef 指出 5.1.2/14 解释了在捕获子句中命名引用时会发生什么。据我所知,这允许我们对第一个示例使用以下解决方法:
int global;
struct s {
int x;
void memfun() {
auto& cx = x;
auto& cglob = global;
[cx,cglob]{};
}
};
蒂亚, 推销
【问题讨论】:
-
注意:C++14 扩展了可能的捕获子句集