在C++中,“保留状态”是什么意思?

7
我在MSDN页面上阅读了有关Lambda表达式优于函数对象和函数指针的优点的解释。所谓的“保留状态”能力是什么意思?它是否与在封闭作用域中通过引用或值捕获某些变量的能力有关?

http://msdn.microsoft.com/en-us/library/dd293608.aspx

当编写代码时,您可能会使用函数指针和函数对象来解决问题和执行计算。函数指针和函数对象都有优点和缺点:函数指针涉及最少的语法开销,但它们不在作用域内保留状态;函数对象可以维护状态,但它们需要类定义的语法开销。
Lambda表达式是一种编程技术,它结合了函数指针和函数对象的优点,并避免了它们的缺点。Lambda表达式灵活,可以像函数对象一样维护状态,其紧凑的语法消除了函数对象所需的类定义的需要。Lambda表达式使您能够编写比等效函数对象更不繁琐且更不容易出错的代码。
以下示例将使用lambda表达式与使用函数对象进行比较。第一个示例使用lambda表达式打印向量对象中每个元素是偶数还是奇数。第二个示例使用函数对象完成相同任务。
您可以参考以下相关参考资料,了解作用域、状态、维护状态和lambda表达式的优点:
- 《C++ Primer》 - 《Effective C++》 - https://en.cppreference.com/w/cpp/language/lambda
1个回答

13

函数对象和Lambda表达式都有一个特性,那就是它们可以记住函数调用之间的状态。普通函数只有静态变量,但这些静态变量是全局唯一的,如果你想要拥有自己独特状态的不同函数对象,那么这是无法实现的。下面是一个函数对象类的例子:

class Counter
{
    int n;
public:
    Counter() :n(0) {}
    int operator()() { return n++; }    
};

通过这个类,我可以创建一个像函数一样的实例,每次调用它时,它会记住n的先前值,例如:

Counter x;
cout << x() << '\n';
cout << x() << '\n';
cout << x() << '\n';

使用普通函数是无法实现这个操作的。但是你可以使用lambda函数:

int n = 0;
auto x = [=]() mutable { return n++; };
cout << x() << '\n';
cout << x() << '\n';
cout << x() << '\n';

2
嗯...你不需要在lambda定义中加入mutable才能使其工作吗? - Matthieu M.
@MatthieuM。是的,谢谢。我几乎总是通过引用捕获,所以我忘了那个。 - Benjamin Lindley
@BenjaminLindley 但是当通过引用捕获时,您也需要一个可变对象来修改所引用的对象,不是吗? - Christian Rau
3
@ChristianRau:不需要的。这是因为即使在const函数中,带有引用成员的类也可以自由修改所引用的内容。因为所引用的内容并不是实际的成员。 - Benjamin Lindley

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接