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呢?我上面的想法有什么错误的地方吗?
智能指针甚至不需要元素类型是可移动的。他们从不尝试以任何形式制作任何副本。所有make_shared要做的就是构造一个对象一次,然后shared_ptr只传递一个指向该单个对象的指针。
复制 ashared_ptr就像复制原始指针(当然还要加上引用计数)。它不会复制所指向的对象。
new如果您手动所做的只是用于创建一次然后处理生成的原始指针(的副本),则您不需要该类型是可复制或可移动的。