睡眠影响 std::thread 调用哪个虚拟成员函数?
Sleep affecting which virtual member function is called by std::thread?
我不确定这是否是 c++11 中的预期行为。这是我发现的一个例子。
#include <iostream>
#include <thread>
using namespace std;
class A {
public:
virtual void a() = 0;
thread t;
A() : t(&A::a, this) {}
virtual ~A() {
t.join();
}
};
class B : public A {
public:
virtual void a() {
cout << "B::a" << endl;
}
};
int main() {
B b;
this_thread::sleep_for(chrono::seconds(1));
}
编译并运行时
$ g++ -std=c++11 -pthread test.cpp -o test
$ ./test
B::a
$
但是当睡眠被移除时...
int main() {
B b;
//this_thread::sleep_for(chrono::seconds(1));
}
奇怪的事情发生了
$ g++ -std=c++11 -pthread test.cpp -o test
$ ./test
pure virtual method called
terminate called without an active exception
Aborted (core dumped)
$
这可能是一个错误吗?
在构造函数和析构函数中时,virtual
函数的行为不同。在A
的构造函数中,B
尚未初始化,这就是为什么B
的虚函数还不可能被调用的原因。请参阅virtual
:
的非静态数据成员期间,例如在成员初始值设定项列表中),并且调用适用的对象是正在构造或销毁的对象,则调用的函数是构造函数或析构函数类中的最终重写器,而不是在派生更多的类中重写它。换句话说,在构造或销毁期间,更多派生的类不存在。
因此,该成员函数指针在调用它时&A::a
在其他线程中解析。此调用解析使用虚拟表,因为&A::a
是指向虚拟成员函数的指针。构造函数做的第一件事是将虚拟表指针设置为类的虚拟表。如果在调用(this->&A::a)()
时已输入B
构造函数,则调用B::a
。调用(this->&A::a)()
的新线程与执行A
和B
构造函数的当前线程之间存在争用条件。
一篇关于从构造函数启动线程的好文章
https://rafalcieslak.wordpress.com/2014/05/16/c11-stdthreads-managed-by-a-designated-class/
相关文章:
- 虚拟成员函数的定义是否强制在同一转换单元中动态初始化静态数据成员?
- 如果我必须覆盖非虚拟成员函数怎么办
- 非虚拟成员函数是否可以使用模板参数?
- 如何将已实现的虚拟成员函数作为参数传递
- 睡眠影响 std::thread 调用哪个虚拟成员函数?
- GTEST:嘲笑非虚拟成员函数
- 虚拟和非虚拟成员函数的调用方式有什么区别?
- 默认情况下是虚拟成员函数
- 为什么在已删除的指针上调用非虚拟成员函数是未定义的行为
- C++标准是否保证了没有虚拟成员函数的类类型的大小
- 在非构造"object"上调用非虚拟成员函数是否定义良好?
- 指向虚拟成员函数的指针是否具有可比性
- 通过指针访问私有虚拟成员函数
- 如何获取"direct"函数指向虚拟成员函数的指针?
- 将 decltype 与虚拟成员函数指针一起使用
- 如何使用基类指针调用派生类非虚拟成员函数,而无需类型转换和使用多态性
- 如何清理已由虚拟成员函数分配的资源
- 具有函数体的纯虚拟成员函数的意义何在
- 在现代CPU中,虚拟成员函数对局部性是好是坏
- 将指向虚拟成员函数的指针作为普通C函数的参数传递