如何使用不可复制不可移动class的对象成员函数启动线程?

How to start thread using object member function of non-copyable non-movable class?

为什么下面的代码无法在 Visual Studio 2015 中编译。

如果 运行 在 ideone 上,相同的代码可以正常工作。

class FooMutex
{
    std::mutex stm;
public:
    void foo() {}
};

int main()
{
    FooMutex o;
    std::thread t1(&FooMutex::foo, o);
}

Error is: C2664 'std::tuple<void (__thiscall FooMutex::* )(void),FooMutex>::
tuple(std::tuple<void (__thiscall FooMutex::* )(void),FooMutex> &&)'
: cannot convert argument 1 from 'void (__thiscall FooMutex::* )(void)' to 'std::allocator_arg_t'

有多种方法可以满足您的需求:

  • 改为传递指针:std::thread t1(&FooMutex::foo, &o);
  • 使用std::bindstd::thread t1(std::bind(&FooMutex::foo, &o));
  • 使用std::bindstd::thread t1(&FooMutex::foo, std::ref(o));
  • 使用 lambda 函数:std::thread t1([&o]() { o.foo(); });

第3、2种方式与第一种方式基本相同。第 4 个实际上有可能成为最有效的一个,因为 lambda 的大小将小于同时包含指针和成员函数指针的可调用对象,因此更有可能嵌入到内部 std::function 对象中,而不是在堆上分配。并不是说它改变了什么,但仍然如此。