weak_ptr,lambda捕获列表中的shared_ptr和std :: queue :: emplace

问题描述 投票:2回答:1

想象一下,我有一个函数使用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中捕获该对象。模板

c++ lambda capture weak-ptr emplace
1个回答
2
投票

问题是,在情况2中,task共享指针未保存在任何地方,并且从wc返回后,保存在lambda捕获中的弱指针submit就会过期。调用lambda时,wc.lock()返回空指针。

© www.soinside.com 2019 - 2024. All rights reserved.