gpt4 book ai didi

c++ - 在 C++ lambda 表达式中按值捕获是否需要使用 lambda 对象复制值?

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:00:57 32 4
gpt4 key购买 nike

标准是否定义了这段代码会发生什么?

#include <iostream>

template <typename Func>
void callfunc(Func f)
{
::std::cout << "In callfunc.\n";
f();
}

template <typename Func>
void callfuncref(Func &f)
{
::std::cout << "In callfuncref.\n";
f();
}

int main()
{
int n = 10;
// n is captured by value, and the lambda expression is mutable so
// modifications to n are allowed inside the lambda block.
auto foo = [n]() mutable -> void {
::std::cout << "Before increment n == " << n << '\n';
++n;
::std::cout << "After increment n == " << n << '\n';
};
callfunc(foo);
callfunc(foo);
callfuncref(foo);
callfunc(foo);
return 0;
}

使用 g++ 的输出是:

$ ./a.out 
In callfunc.
Before increment n == 10
After increment n == 11
In callfunc.
Before increment n == 10
After increment n == 11
In callfuncref.
Before increment n == 10
After increment n == 11
In callfunc.
Before increment n == 11
After increment n == 12

这个输出的所有特性都是标准所要求的吗?

特别是,如果创建了 lambda 对象的拷贝,那么所有捕获的值也会被复制。但是,如果通过引用传递 lambda 对象,则不会复制任何捕获的值。并且在调用函数之前不会对捕获的值进行复制,因此捕获值的突变会在调用之间保留。

最佳答案

lambda 的类型只是一个类 (n3290 §5.1.2/3),带有一个执行主体 (/5) 的 operator() 和一个隐式复制构造函数 (/19), 而通过拷贝捕获一个变量相当于将它拷贝初始化(/21)到这个类的一个非静态数据成员(/14)中,每次使用那个变量都会被对应的数据成员(/17).经过这样的改造,lambda表达式只变成了这个类的一个实例,遵循C++的通用规则。

这意味着,您的代码将以与以下相同的方式工作:

int main()
{
int n = 10;

class __Foo__ // §5.1.2/3
{
int __n__; // §5.1.2/14
public:
void operator()() // §5.1.2/5
{
std::cout << "Before increment n == " << __n__ << '\n';
++ __n__; // §5.1.2/17
std::cout << "After increment n == " << __n__ << '\n';
}
__Foo__() = delete;
__Foo__(int n) : __n__(n) {}
//__Foo__(const __Foo__&) = default; // §5.1.2/19
}
foo {n}; // §5.1.2/21

callfunc(foo);
callfunc(foo);
callfuncref(foo);
callfunc(foo);
}

很明显 callfuncref 在这里做了什么。

关于c++ - 在 C++ lambda 表达式中按值捕获是否需要使用 lambda 对象复制值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10073709/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com