【问题标题】:Passing a std::shared_ptr to a function object to std::thread将 std::shared_ptr 传递给函数对象到 std::thread
【发布时间】:2017-03-22 20:26:17
【问题描述】:

需要让这个 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>我在这段代码中做了什么?!

【问题讨论】:

  • 不应该是std::thread t(*fp)吗?

标签: c++ multithreading c++11 shared-ptr functor


【解决方案1】:

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

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

INVOKE(f, t1, t2, ..., tN) 等价于 f(t1, t2, ..., tN)(即 是,f是一个FunctionObject)

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

2>如何确保分配给线程的资源一直存在 和线程一样?

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

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

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

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

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

Demo

【讨论】:

  • 感谢您的回答@themagiacalyang,但回到 3>什么是 c++ 中的函子,我遇到有人说定义 operator() 的对象是函子或函数对象。 1>我需要进一步探索这一点,但我能够做到std::thread((Functor())),它确实打印Hello!,而无需显式传递 operator()。
  • @user3222 是的。该演示仅供参考,以了解如何显式传递operator()Functor() 充当函数对象。简而言之 f 是一个函数对象,如果您可以对其执行 f(...) ,其中 ... 是参数。
【解决方案2】:

std::shared_ptr&lt;Functor&gt; 不可调用 - 它不实现 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;
}

【讨论】:

    【解决方案3】:

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

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

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

    缺点:消除了具有仿函数的好处,因为您必须指定成员函数。

    【讨论】:

      猜你喜欢
      • 2020-12-15
      • 1970-01-01
      • 2012-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-01
      相关资源
      最近更新 更多