标准是否定义了此代码会发生什么?
#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;
}
Run Code Online (Sandbox Code Playgroud)
用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
Run Code Online (Sandbox Code Playgroud)
标准是否需要此输出的所有功能?
特别是看起来,如果创建了lambda对象的副本,则还会复制所有捕获的值.但是,如果通过引用传递lambda对象,则不会复制捕获的值.并且在调用函数之前不会复制捕获的值,因此在调用之间保留对捕获值的突变.
lambda的类型只是一个类(n3290§5.1.2/ 3),其中一个operator()执行主体(/ 5),一个隐式复制构造函数(/ 19),并通过复制捕获一个变量等同于复制-initialize(/ 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);
}
Run Code Online (Sandbox Code Playgroud)
显而易见的是callfuncref这里有什么.