首页 > 解决方案 > list.erase 中的 Lambda 表达式

问题描述

我正在学习 lambdas 并尝试各种示例,但我不确定我明白为什么这不起作用:

std::list<int> listIntegers;
listIntegers.push_back(40);

listIntegers.erase([listIntegers]() {
return std::find(listIntegers.begin(), listIntegers.end(), 40);
});

我也试图明确地写:

listIntegers.erase([listIntegers]()->std::list<int>::const_iterator {
    return std::find(listIntegers.begin(), listIntegers.end(), 40);
    });

然而,这当然有效:

auto found40Iterator = std::find(listIntegers.begin(), listIntegers.end(), 40)

listIntegers.erase(found40Iterator);

标签: c++listlambdastdlist

解决方案


考虑的情况

listIntegers.erase([listIntegers]()->std::list<int>::const_iterator {
    return std::find(listIntegers.begin(), listIntegers.end(), 40);
});

捕获列表按值[listIntegers]获取listInteger,副本与 lambda 一起存储。由于listIntegers使用的 instd::find(listIntegers.begin(), listIntegers.end(), 40)是原件的副本,因此它将40在该副本中找到元素。因此,返回的迭代器是副本中元素的迭代器,而不是原始元素的迭代器。迭代器只能与来自同一容器的其他迭代器及其原始容器一起使用。您看到的问题是您的 lambda 的返回值正在使用,listIntegers但它实际上是指不同范围内的元素(的副本listIntegers)。

解决方案是更改您的捕获列表以listIntegers通过引用获取,以便它将在原始listIntegers. 还有一个问题是您没有调用 lambda,而是将其作为参数传递给erase. 通过添加一对括号,我们可以改为调用 lambda 并将其返回值传递给erase.

listIntegers.erase([&listIntegers]() {
    // Added & here ^
    return std::find(listIntegers.begin(), listIntegers.end(), 40);
}());
//^ Call the lambda

推荐阅读