gpt4 book ai didi

c++ - 容器如何处理 lambda 表达式的参数

转载 作者:行者123 更新时间:2023-11-30 04:57:45 25 4
gpt4 key购买 nike

继我几个月前的上一个问题之后,我想问一下容器如何在内部处理 lampda 表达式。

假设以下一段代码:

#include <iostream>
#include <type_traits>
#include <queue>
#include <functional>

std::queue<std::function<void()>> funcs;

class A
{
public:
A()
{
std::cout << "A constructor" << std::endl;
}
void foo(int a)
{
}
};

class ThePool
{
public:
template <typename _Callable, typename Object, typename... _Args>
void QueueFunction(_Callable __f, Object& obj, _Args... __args)
{
funcs.push([__f, &obj, &__args...]() mutable
{
(obj.*__f)(__args...);
});
}
};

int main(int argc, char** argv)
{
ThePool t;
A a;
int x = 5;
t.QueueFunction(&A::foo, a, x);
std::function<void()> func = funcs.back();
func();
return 0;
}

如果将类 A 的实例和 args 作为值传递,则很明显值已被复制。如果我将类 A 的实例作为引用传递,并将 args 作为引用传递,我会混淆会发生什么。我知道在容器内部发生复制。从我的角度来看,函数指针的地址将被复制。是否也复制了 obj 和 args 的实例?

举个例子,我注意到当我将 A 实例作为引用传递并最终提取队列的函数 f 并将其称为 A 的实例时,这是不一样的。

最佳答案

容器确实可以自由复制其元素。此外,std::function 具有 requirement存储仿函数是 CopyConstructible,它肯定会使用它。因此,您必须选择:

  • 如果按值传递对象,您实际上不必担心对象的生命周期。但是,在对象的拷贝(或使用复制的参数)上调用成员函数可能不是您想要的。

  • 如果您通过(某种形式的)引用传递对象(例如将它们包装在 std::ref 中),您将永远不会创建对象和参数的拷贝,但它们可能会消失在调用排队成员函数之前的作用域。

Currently 在您的原始代码中,您正在 lambda 中创建 obj 的拷贝(obj 是一个 Obj& 但这对 lambda 捕获无关紧要——如果没有通过引用显式捕获,它会复制)。要改为在 lambda 中保留引用,请按引用 ([&obj]) 而不是按值捕获 obj。或者,传递包装在 std::ref 中的对象。

至于参数,它们目前都是复制的(在 QueueFunction 中以及 lambda 捕获中)。如果这不是您的意图,请参阅上文。

如果你存储引用,那么开头提到的所有复制操作只会复制引用(而不是对象)。

关于c++ - 容器如何处理 lambda 表达式的参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51963167/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com