在最近的一个C++ 0x草案(n3225.pdf)中,我们可以找到5.1.2/10:
使用通常的非限定名称查找规则(3.4.1)查找捕获列表中的标识符; 每个这样的查找应该找到一个变量,其自动存储持续时间在本地lambda表达式的到达范围内声明.如果实体(即变量或此实体)出现在lambda表达式的捕获列表中,则称其被明确捕获.
这对我来说似乎相当严格.例如,在我看来,以下事情是不允许的:
int global;
struct s {
int x;
void memfun() {
[x,global]{};
}
};
Run Code Online (Sandbox Code Playgroud)
因为x不一定是具有自动存储的变量,也不是global.请注意,此捕捉条款的用意是让拉姆达对象存储复制的x,并global可能是可取的情况下,他们在后一阶段发生变化.我已经知道了另一种选择:
int global;
struct s {
int x;
void memfun() {
int copyx = x;
int copyglobal = global;
[copyx,copyglobal]{};
}
};
Run Code Online (Sandbox Code Playgroud)
但这归结为额外的副本和额外的锅炉板只是为了捕获x和global复制.
此外,我在最新的草稿中找不到任何结论,如果我们在捕获子句中命名本地引用会发生什么:
int main() {
int i = 0;
int &r = i;
assert([r]{return &r;}() != &i);
}
Run Code Online (Sandbox Code Playgroud)
lambda对象"复制引用"还是"复制int"?如果它通过副本捕获引用的对象,这可以节省我们之前的解决方案中的其他副本.
GCC显然支持所有这些示例,并在最后一种情况下存储一个int的副本(这是可取的,恕我直言).但我想知道这是否实际上是根据C++ 0x草案的预期行为,或者只是一个编译器扩展,分别是一个实现bug.
编辑:
templatetypedef指出5.1.2/14,它解释了在capture-clause中命名引用时会发生什么.据我所知,这允许我们在第一个例子中使用以下解决方法:
int global;
struct s {
int x;
void memfun() {
auto& cx = x;
auto& cglob = global;
[cx,cglob]{};
}
};
Run Code Online (Sandbox Code Playgroud)
Tia,sellibitze
tem*_*def 11
根据您发布的内容,您的第一个示例似乎是非法的,因为两个捕获的变量都没有自动持续时间. 但是,您可以轻松解决此问题.要捕获数据成员,您可以捕获它,并且不需要捕获全局,因为您可以直接引用它.
编辑:正如您所指出的,这不会创建您要捕获的值的本地副本. 要在制作副本时捕获这些变量,您可以捕获它,然后在lambda中显式创建数据成员的本地副本.
关于捕获引用的第二个问题,§5.1.2/ 14表示通过复制捕获引用类型的变量将创建引用值的副本,而不是创建引用的副本.因此,lambda将拥有自己的值副本,引用在创建时引用该值.
| 归档时间: |
|
| 查看次数: |
1894 次 |
| 最近记录: |