且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

lambda的捕获变量被重置

更新时间:2023-11-11 12:31:10

该变量未重置,这是变量的另一个副本。实际上,有一堆副本。第一个处于您创建的lambda的状态。第二个是在构造第一个 std :: function 时创建的。您必须记住,它将接收到的可调用对象复制到其自身中。因此,每次 tester 的调用都会启动一连串的副本。解决该问题的一种方法是在 std :: reference_wrapper

The variable isn't reset, it's a different copy of the variable. In fact, there are a bunch copies. The first is in the state of the lambda you create. The second is created when the first std::function is constructed. You must remember that it copies the callable it receives into itself. So each invocation of tester starts a chain of copies. One way to get around it, is to pass the lambda inside a std::reference_wrapper.

tester(std::ref(getNum));
tester(std::ref(getNum));

将复制引用包装,但所有副本将引用同一个lambda对象, getNum

The reference wrapper will be copied, but all copies will refer to the same lambda object, getNum.

现在,假设您打算创建许多不同的对象,例如 getNum std :: function 及其提供的类型擦除是避免可能的代码膨胀的合理做法。要记住的是不要创建多余的副本。因此,按值接受 tester 是合法的,但 tester_wrapper 应该代替引用。这样一来,您只需在API边界的所需位置购买类型擦除即可。

Now, assuming you intend to create many different objects like getNum, a std::function and the type erasure it provides are a reasonable course of action to avoid possible code bloat. The thing to remember is to not create superfluous copies. So tester accepting by value is legitimate, but tester_wrapper should accept by reference instead. That way, you'll only pay for the type erasure in the one place you need it, at the API boundary.