如何使用不可复制不可移动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::bind
:std::thread t1(std::bind(&FooMutex::foo, &o));
- 使用
std::bind
:std::thread t1(&FooMutex::foo, std::ref(o));
- 使用 lambda 函数:
std::thread t1([&o]() { o.foo(); });
第3、2种方式与第一种方式基本相同。第 4 个实际上有可能成为最有效的一个,因为 lambda 的大小将小于同时包含指针和成员函数指针的可调用对象,因此更有可能嵌入到内部 std::function
对象中,而不是在堆上分配。并不是说它改变了什么,但仍然如此。
为什么下面的代码无法在 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::bind
:std::thread t1(std::bind(&FooMutex::foo, &o));
- 使用
std::bind
:std::thread t1(&FooMutex::foo, std::ref(o));
- 使用 lambda 函数:
std::thread t1([&o]() { o.foo(); });
第3、2种方式与第一种方式基本相同。第 4 个实际上有可能成为最有效的一个,因为 lambda 的大小将小于同时包含指针和成员函数指针的可调用对象,因此更有可能嵌入到内部 std::function
对象中,而不是在堆上分配。并不是说它改变了什么,但仍然如此。