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

Visual studio 如何使用不可复制不可移动类的对象成员函数启动线程?,visual-studio,function,c++11,stdthread,Visual Studio,Function,C++11,Stdthread,为什么下面的代码没有在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 F

为什么下面的代码没有在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'
class-FooMutex
{
std::互斥stm;
公众:
void foo(){}
};
int main()
{
foomutexo;
std::线程t1(&FooMutex::foo,o);
}
错误为:C2664'std::tuple::
元组(std::tuple&)'
:无法将参数1从“void(\u thiscall FooMutex::*)(void)”转换为“std::allocator\u arg\u t”

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

  • 而是传递指针:
    std::threadt1(&FooMutex::foo,&o)
  • 使用
    std::bind
    std::threadt1(std::bind(&FooMutex::foo,&o))
  • 使用
    std::bind
    std::threadt1(&FooMutex::foo,std::ref(o))
  • 使用lambda函数:
    std::threadt1([&o](){o.foo();})

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

foo不接受任何参数。@jdigital Yes foo不接受任何参数,我想调用成员函数,所以我也需要传递对象。我知道还有其他方法可以实现它,但我想理解为什么visual studio会抛出错误,而ideone不会。这个特定的代码是否依赖于编译器?另外,如果我删除std::mutex,那么它会编译得很好。@Daemon可能是因为您使用的是不同的编译器,其中一个是错误的
std::mutex
是一个不可复制和不可移动的类,一旦将其添加到类中,类也将变得不可复制和不可移动。没有
std::mutex
它可以被复制。你也可以使用
std::ref(o)
通过
std::thread
的构造函数通过引用传递
o
。@Ivan有没有办法找到那个bug或者找到更多关于这个的信息。我正在使用VisualStudio2015@Daemon您需要构建此代码的编译器-这是错误的。参数应由
std::thread
构造函数复制或移动。如果实现没有做到这一点,那就是错误的。您可以阅读
std::thread
构造函数的工作原理。顺便说一句,ideone使用的默认编译器不会生成它。