[英]lambda function doesn't work in priority_queue in c++ (when using [&])
[英]Polymorphism doesn't work in C++ lambda function
我有这样的方法:
void syncOperation(ProgressCallback& progressCallback);
其中ProgressCallback
为:
class ProgressCallback
{
public:
virtual void onProgress(std::size_t currValue, std::size_t maxValue) {}
virtual void onDone() {}
};
并且我想使其异步,因此请执行以下操作:
void asyncOperation(ProgressCallback& progressCallback)
{
auto impl = [this](ProgressCallback& progressCallback_)
{
syncOperation(progressCallback_);
};
jobsPool.addJob(std::bind(impl, progressCallback));
}
但是在asyncOperation(ProgressCallback&)
情况下( asyncOperation(ProgressCallback&)
) progressCallback
行为不是多态的,它始终会调用基类的方法,这绝对不是我期望的。 所以我的问题是:1)为什么会发生这种情况; 2)如何解决它(是的,我知道我可以停止使用lambda了,但是也许有一些传统的解决方法)?
您显示的代码没有多态的余地,但是让我们假设asyncOperation
传递了对从ProgressCallback
派生的东西的引用:
将引用传递给bind
时,您正在创建一个副本。 绑定返回的对象根据其具有的类型信息存储值。 它只知道它具有对ProgressCallback
的引用,因此它存储的是哪种值。 这将导致切片副本。
您需要将值包装在reference_wrapper中:
jobsPool.addJob(bind(impl, ref(progressCallback));
或者您可以使用lambda(更好):
jobsPool.addJob([impl,&progressCallback](){ impl(progressCallback); });
或者,您也可以创建impl
以便它自己执行所有操作。
您现在所要做的相对相当于:
jobsPool.addJob([impl,=progressCallback]() mutable { impl(progressCallback); });
您无需定义一个lambda,然后使用bind或使用两个lambda,就可以一次完成所有操作:
void asyncOperation(ProgressCallback& progressCallback)
{
jobsPool.addJob([&] { syncOperation(progressCallback); });
}
如前所述,在原始代码中,由于正在切片切片,您被咬了。 由于模板参数推导的工作原理,像std::bind
这样的延迟函数调用需要具有通过引用包装传递的按引用参数。 这种相当奇怪的行为是一旦访问lambda便根本不使用bind
另一个很好的理由。 但是请注意,此行为也适用于std::thread
。
请注意,存储通过引用捕获某些东西的lambda是一件非常危险的事情。 您可以使用一个progressCallback对象调用asyncOperation
,然后该对象仍处于活动状态,并且有可能在执行lambda时破坏了该对象,从而导致不确定的行为。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.