想象一下,我有一个函数使用std :: queue的内置emplace来使lambda入队。我创建了shared_ptr对象(任务),稍后我将在lambda中捕获。
template<typename Func, typename... Args>
auto submit(Func&& f, Args&&... args)
{
using result_type = std::result_of_t<Func(Args...)>;
using pckg_task_type = std::packaged_task<result_type()>;
auto task = std::make_shared< pckg_task_type >(
std::bind(std::forward<Func>(f), std::forward<Args>(args)...) );
...
}
现在是让我非常困惑的部分...
案例1:
tasks.emplace(
[task](){
auto wptr = std::weak_ptr<pckg_task_type>(task);
if( auto p = wptr.lock() )
{
(*p)();
}
else
throw std::runtime_error("weak error");
}
);
此案子就像一个护身符。没问题。
案例2]]
tasks.emplace( [wc = std::weak_ptr<pckg_task_type>(task)](){ if( auto p = wc.lock() ) { (*p)(); } else throw std::runtime_error("weak error"); } );
任务定义为
,立即触发异常。std::queue< std::function<void()> > tasks;
案例No.2
从情况2调用lambda而不将其放入队列不会引发异常。
谁能解释上述情况之间的区别?问题出在哪里?
想象一下,我有一个函数使用std :: queue的内置emplace来使lambda入队。我创建了shared_ptr对象(任务),稍后我将在lambda中捕获该对象。模板
问题是,在情况2中,task
共享指针未保存在任何地方,并且从wc
返回后,保存在lambda捕获中的弱指针submit
就会过期。调用lambda时,wc.lock()
返回空指针。