将 std::shared_ptr 传递给函数对象 std::thread

Passing a std::shared_ptr to a function object to std::thread

需要让这个 Functor 和我的线程一样长,所以我为它创建了一个 shared_ptr 并试图将它传递给 std::thread。我已经在此处复制了代码和错误列表。

struct Functor
{
    std::string greeting;
    explicit Functor(std::string _greeting="Hello!"): greeting { _greeting }     {}
    void operator()()
    {
        std::cout << greeting << "\n";
    }
};

auto main() ->int 
{
    std::shared_ptr<Functor> fp = std::make_shared<Functor> ();
    std::thread t(&fp);
    t.join();
    return 0;
}

错误列表:

Error   C2893   Failed to specialize function template 'unknown-type std::invoke(_Callable &&,_Types &&...)'    std_threads C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\thr\xthread  240 
Error   C2672   'std::invoke': no matching overloaded function found    std_threads C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\thr\xthread  240 

我是 c++11 和并发的新手。请帮助我理解以下内容

1>当按值传递时,std::thread 是否总是在对象内部调用 operator()?如果是,为什么这么定义。

2>如何确保提供给线程的资源与线程一样长?

3>这里写的Functor是函数对象吗?

4>我在这段代码中做了什么?!

1>does a std::thread always invoke the operator() inside an object when passed by value ? If so, why it has been defined so.

std::thread 调用 std::invoke。来自 cppreference,如果第一个参数既不是 pointer to member function 也不是 pointer to data member;它被视为一个函数对象。 因此,将调用 fp()。

INVOKE(f, t1, t2, ..., tN) is equivalent to f(t1, t2, ..., tN) (that is, f is a FunctionObject)

所以你基本上可以做到std::thread t{*fp}

2>how to ensure that a resource given to a thread stays around as long as the thread does?

您可以 shared_ptr 提供共享对象的所有权。或者您可以通过确保传递的资源在范围内来手动执行此操作。里程不同。

3>is the Functor written here, a function object ?

是的。 FunctionObject 类型是可以在函数调用运算符左侧使用的对象类型。但是 fp 不是。但是 *fp 是。

4>What have I done here in this code ?!

您可以通过显式传递带有参数 fp.get()Functor::operator() 来使其工作。当然,一个简单的方法就是传递 *fp

Demo

std::shared_ptr<Functor> 不可调用 - 它不实现 operator(),即使 Functor 实现。

这里shared_ptr的目的是什么?为什么不干脆

int main() {
    Functor f;
    std::thread t(std::ref(f));
    t.join();
    return 0;
}

如果出于某种原因您坚持让 Functor 实例由 shared_ptr 管理,这是一种方法:

int main() {
    std::shared_ptr<Functor> fp = std::make_shared<Functor> ();
    std::thread t([fp]() { (*fp)(); });
    t.join();
    return 0;
}

您仍然可以使用以下语法让 std::thread 取得您的智能指针的所有权:

std::shared_ptr<Functor> f = std::make_shared<Functor>();
std::thread thread (&Functor::operator(), f);
thread.detach();

如果第一个参数是成员函数指针,那么第二个参数应该是对 class 实例的引用或指针,并且接受 std::shared_ptr<Functor>。当线程结束时,智能指针将被删除。

缺点:失去了使用仿函数的好处,因为您必须指定成员函数。