首页 > 解决方案 > 如何使用不可复制不可移动类的对象成员函数启动线程?

问题描述

为什么下面的代码无法在 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'

标签: visual-studiofunctionc++11stdthread

解决方案


有多种方法可以做你想做的事:

  • 改为传递指针: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(); });

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


推荐阅读