C ++ 11:类中的 std::thread 在构造函数中执行具有线程初始化的函数成员
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5956759/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C++11: std::thread inside a class executing a function member with thread initialisation in the constructor
提问by Mooks
I'm trying to use std::thread from C++11. I couldn't find anywhere if it is possible to have a std::thread inside a class executing one of its function members. Consider the example below... In my try (below), the function is run().
我正在尝试使用 C++11 中的 std::thread。如果在执行其函数成员之一的类中可以有一个 std::thread,我找不到任何地方。考虑下面的例子......在我的尝试中(下面),函数是 run()。
I compile with gcc-4.4 with -std=c++0x flag.
我使用带有 -std=c++0x 标志的 gcc-4.4 进行编译。
#ifndef RUNNABLE_H
#define RUNNABLE_H
#include <thread>
class Runnable
{
public:
Runnable() : m_stop(false) {m_thread = std::thread(Runnable::run,this); }
virtual ~Runnable() { stop(); }
void stop() { m_stop = false; m_thread.join(); }
protected:
virtual void run() = 0;
bool m_stop;
private:
std::thread m_thread;
};
class myThread : public Runnable{
protected:
void run() { while(!m_stop){ /* do something... */ }; }
};
#endif // RUNNABLE_H
I'm getting this error and others: (same error with and without the $this)
我收到此错误和其他错误:(使用和不使用 $this 时出现相同的错误)
Runnable.h|9|error: no matching function for call to ‘std::thread::thread(<unresolved overloaded function type>, Runnable* const)'|
When passing a pointer.
传递指针时。
Runnable.h|9|error: ISO C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function. Say ‘&Runnable::run'|
回答by ildjarn
Here's some code to mull over:
这是一些需要仔细考虑的代码:
#ifndef RUNNABLE_H
#define RUNNABLE_H
#include <atomic>
#include <thread>
class Runnable
{
public:
Runnable() : m_stop(), m_thread() { }
virtual ~Runnable() { try { stop(); } catch(...) { /*??*/ } }
Runnable(Runnable const&) = delete;
Runnable& operator =(Runnable const&) = delete;
void stop() { m_stop = true; m_thread.join(); }
void start() { m_thread = std::thread(&Runnable::run, this); }
protected:
virtual void run() = 0;
std::atomic<bool> m_stop;
private:
std::thread m_thread;
};
class myThread : public Runnable
{
protected:
void run() { while (!m_stop) { /* do something... */ }; }
};
#endif // RUNNABLE_H
Some notes:
一些注意事项:
- Declaring
m_stop
as a simplebool
as you were is horribly insufficient; read up on memory barriers std::thread::join
can throw so calling it without atry..catch
from a destructor is recklessstd::thread
andstd::atomic<>
are non-copyable, soRunnable
should be marked as such, if for no other reason than to avoid C4512 warnings with VC++
- 像你
m_stop
这样简单地声明bool
是远远不够的;阅读内存屏障 std::thread::join
可以抛出所以在没有try..catch
析构函数的情况下调用它是鲁莽的std::thread
并且std::atomic<>
是不可复制的,所以Runnable
应该被标记为这样,如果没有其他原因,除了避免 VC++ 的 C4512 警告
回答by David Rodríguez - dribeas
That approach is wrong.
这种做法是错误的。
The problem is that while the object is still under construction its type is still not the most derived type, but the type of the constructor that is executing. That means that when you start the thread the object is still a Runnable
and the call to run()
can be dispatched to Runnable::run()
, which is pure virtual, and that in turn will cause undefined behavior.
问题是,虽然对象仍在构造中,但它的类型仍然不是最派生的类型,而是正在执行的构造函数的类型。这意味着当您启动线程时,对象仍然是 aRunnable
并且run()
可以将调用分派到Runnable::run()
,这是纯虚拟的,这反过来会导致未定义的行为。
Even worse, you might run into a false sense of security, as it might be the case that under some circumstances the thread that is being started might take long enough for the current thread to complete the Runnable
constructor, and enter the myThread
object, in which case the new thread will execute the correct method, but change the system where you execute the program (different number of cores, or the load of the system, or any other unrelated circumstance) and the program will crash in production.
更糟糕的是,您可能会遇到错误的安全感,因为在某些情况下,正在启动的线程可能需要足够长的时间来让当前线程完成Runnable
构造函数并进入myThread
对象,在这种情况下新线程将执行正确的方法,但更改您执行程序的系统(不同的内核数,或系统的负载,或任何其他无关的情况),程序将在生产中崩溃。