简体   繁体   English

lambda 捕获列表和 std::queue 中的weak_ptr、shared_ptr<T,Container> ::驻地

[英]weak_ptr, shared_ptr in lambda capture list and std::queue<T,Container>::emplace

I have a function which enqueue lambda using std::queue's build-in emplace.我有一个函数,它使用std::queue's内置 emplace 对 lambda 进行std::queue's I created shared_ptr object (task), which later I would capture in 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)...) );
        ...
    }

This is the part which is creating confusion:这是造成混乱的部分:

Case 1: Which works perfectly案例 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");
                }
            );

Case 2: Which immediately throws an exception情况二:立即抛出异常

                tasks.emplace(
                [wc = std::weak_ptr<pckg_task_type>(task)](){
                    if( auto p = wc.lock() )
                    {
                        (*p)();
                    }
                    else
                        throw std::runtime_error("weak error");
                }
            );

With tasks defined as任务定义为

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

Calling lambda from case 2 without emplace it into queue doesn't throw exception.在不将其放入队列的情况下从案例 2 调用 lambda 不会引发异常。

Can anyone explain the difference between cases above?任何人都可以解释上述案例之间的区别吗? Where is the problem?问题出在哪儿?

The problem is that in the case 2 the task shared pointer is not saved anywhere and the weak pointer wc that is saved in the lambda capture expires as soon as you return from submit .问题是在情况 2 中, task共享指针没有保存在任何地方,并且一旦您从submit返回,保存在 lambda 捕获中的弱指针wc就会过期。 When the lambda is invoked, wc.lock() returns a null pointer.当 lambda 被调用时, wc.lock()返回一个空指针。

You probably need to save the task shared_ptr somewhere for the lifetime duration of the enqueued function object.您可能需要在入队函数对象的生命周期内将task shared_ptr保存在某处。 Or you don't need weak_ptr at all and can just save the task shared_ptr in the lambda capture and use it directly in the lambda body.或者您根本不需要weak_ptr ,只需将task shared_ptr保存在lambda 捕获中并直接在lambda 主体中使用它。

Your first case copies the shared pointer into the lambda and will therefore keep it alive for the lifetime of the lambda, the weak pointer inside the lambda is pointless as you create a weak pointer then immediately lock it which will never fail.您的第一种情况将共享指针复制到 lambda 中,因此将在 lambda 的整个生命周期内使其保持活动状态,当您创建一个弱指针然后立即锁定它时,lambda 内的弱指针毫无意义,这将永远不会失败。

The second case is only capturing a weak pointer, the shared pointer goes out of scope at the end of submit and presumably there are no other references to it so the pointer is deleted.第二种情况仅捕获弱指针,共享指针在提交结束时超出范围,并且可能没有其他引用,因此删除指针。 This would only work if your lambda starts executing and locks the pointer before the end of submit.这仅在您的 lambda 开始执行并在提交结束之前锁定指针时才有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM