只能移动的对象可以做成shared_ptr吗?

f1m*_*sch 0 c++ shared-ptr packaged-task

我正在阅读thread_pool的开源代码

它显示

// add new work item to the pool
template<class F, class... Args>
auto ThreadPool::enqueue(F&& f, Args&&... args) 
    -> std::future<typename std::result_of<F(Args...)>::type>
{
    using return_type = typename std::result_of<F(Args...)>::type;

    auto task = std::make_shared< std::packaged_task<return_type()> >(
            std::bind(std::forward<F>(f), std::forward<Args>(args)...)
        );
        
    std::future<return_type> res = task->get_future();
    {
        std::unique_lock<std::mutex> lock(queue_mutex);

        // don't allow enqueueing after stopping the pool
        if(stop)
            throw std::runtime_error("enqueue on stopped ThreadPool");

        tasks.emplace([task](){ (*task)(); });
    }
    condition.notify_one();
    return res;
}
Run Code Online (Sandbox Code Playgroud)

据我所知, std::packaged_task是唯一可移动的对象,那么shared_ptr 可以task由 组成吗std::packaged_task?因为std::packaged_task永远不可能shared

但反过来说,在句子 中tasks.emplace([task](){ (*task)(); });task被值复制到 lambda 中,那么这是否也意味着 share_ptr 中的计数task将被添加到 2 中?这意味着std::packaged_task实际上是被shared复制到 2 个副本中。

那么是否可以将一个只能移动的对象做成shared_ptr呢?我上面的想法有什么错误的地方吗?

use*_*522 7

智能指针甚至不需要元素类型是可移动的。他们从不尝试以任何形式制作任何副本。所有make_shared要做的就是构造一个对象一次,然后shared_ptr只传递一个指向该单个对象的指针。

复制 ashared_ptr就像复制原始指针(当然还要加上引用计数)。它不会复制所指向的对象。

new如果您手动所做的只是用于创建一次然后处理生成的原始指针(的副本),则您不需要该类型是可复制或可移动的。