Cpp-lambda递归调用的问题

Cpp-lambda递归调用的问题

今天写了一个lambda函数:

1
2
3
4
5
6
7
8
9
function<bool(TreeNode*, long long, long long)> isBST = [](TreeNode* root, long long lower, long long upper)
{
if(!root)
return true;
if(root->val <= lower || root->val >= upper)
return false;

return isBST(root->left, lower, root->val) && isBST(root->right, root->val, upper);
};

然后发现报错了:

1
2
3
4
5
6
7
8
Line 23: Char 20: error: variable 'isBST' cannot be implicitly captured in a lambda with no capture-default specified
return isBST(root->left, lower, root->val) && isBST(root->right, root->val, upper);
^
Line 16: Char 57: note: 'isBST' declared here
function<bool(TreeNode*, long long, long long)> isBST = [](TreeNode* root, long long lower, long long upper)
^
Line 16: Char 65: note: lambda expression begins here
function<bool(TreeNode*, long long, long long)> isBST = [](TreeNode* root, long long lower, long long upper)

究其原因是在定义的时候lambda使用了按值捕获,而lambda表达式不能隐式capture,所以需要改成:

1
2
3
4
5
6
7
8
9
10
function<bool(TreeNode*, long long, long long)> isBST = [&](TreeNode* root, long long lower, long long upper)
// ^这里一定要使用引用捕获
{
if(!root)
return true;
if(root->val <= lower || root->val >= upper)
return false;

return isBST(root->left, lower, root->val) && isBST(root->right, root->val, upper);
};

之所以使用引用捕获而不是值捕获,原因是捕获的时候,fact还没有初始化。

这个问题其实和下面的代码问题是一样的:

1
2
3
4
5
int n; // not initialized
const int &ref_n = n;
int val_n = n;
n = 10; // initialized
cout << "n is " << n << ", ref_n is " << ref_n << ", val_n is " << val_n << endl;

输出的结果:

1
n is 10, ref_n is 10, val_n is 4198713

nref_n都能获得正确的值,但val_n就不一定能打印出什么来了。 这就是因为,在使用operator=的时候,val_n将未初始化的n复制了一份,而之后n的初始化和val_n就无关了,所以val_n虽然初始化了,但和没初始化一样。

参考C++中的递归lambda,以及携带额外变量


Cpp-lambda递归调用的问题
https://gstarmin.github.io/2023/06/26/Cpp-lambda递归调用的问题/
作者
Starmin
发布于
2023年6月26日
许可协议