C++11:std::thread 在类中执行函数成员,并在构造函数中初始化线程
C++11: std::thread inside a class executing a function member with thread initialisation in the constructor
我正在尝试使用C++11中的std::thread。如果可以在执行其函数成员之一的类中有一个 std::thread,我找不到任何地方。考虑下面的例子...在我的尝试(下面)中,函数是 run()。
我使用 gcc-4.4 和 -std=c++0x 标志进行编译。
#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
我收到此错误和其他错误:(有和没有$this相同的错误)
Runnable.h|9|error: no matching function for call to ‘std::thread::thread(<unresolved overloaded function type>, Runnable* const)’|
传递指针时。
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’|
这里有一些代码需要仔细考虑:
#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
一些注意事项:
- 像你一样宣称
m_stop
是一个简单的bool
是非常不够的; 阅读记忆障碍 -
std::thread::join
可以投掷,所以在没有析构函数try..catch
的情况下调用它是鲁莽的 -
std::thread
和std::atomic<>
是不可复制的,因此Runnable
应该被标记为不可复制,如果没有其他原因,只是为了避免使用 VC++ 出现 C4512 警告
这种方法是错误的。
问题在于,虽然对象仍在构造中,但其类型仍然不是派生最多的类型,而是正在执行的构造函数的类型。这意味着当你启动线程时,对象仍然是一个Runnable
,对run()
的调用可以调度到Runnable::run()
,这是纯虚拟的,这反过来会导致未定义的行为。
更糟糕的是,您可能会遇到一种虚假的安全感,因为在某些情况下,正在启动的线程可能需要足够长的时间才能使当前线程完成Runnable
构造函数并输入myThread
对象,在这种情况下,新线程将执行正确的方法, 但是更改执行程序的系统(内核数不同,或系统的负载,或任何其他不相关的情况),程序将在生产中崩溃。
相关文章:
- 如何将元素添加到数组的线程安全函数?
- 为什么std::async使用同一个线程运行函数
- 非静态成员失败的线程调用函数
- 线程构造函数周围的可变参数模板包装器无法编译
- 通过std::shared_ptr使用Rcpp和RcppParallel的线程安全函数指针
- 如何解决传递给boost线程的函数中的歧义
- 返回可中断线程的函数
- 包装标准::线程调用函数
- 为什么Win API线程执行函数,而标准线程则没有
- C 好奇的情况将TypeName/DataType名称/类名称传递给线程构造函数
- 线程对象函数 C++
- 为线程构造函数传递引用以将其绑定到函数失败
- C++多线程在函数调用期间避免交错
- 为什么c++中线程构造函数和绑定的函数签名是相同的
- 了解线程构造函数的基础知识
- 线程构造函数如何检测右值引用
- std::线程构造函数(变量的数量)
- C++线程构造函数,使用new(object)会造成内存泄漏
- 如何将类方法传递给另一个函数,就像线程构造函数中发生的那样
- std::线程构造函数中的可移动参数(Visual c++ 2012)