[英]C++11 std::thread and virtual function binding
我遇到了一個奇怪的C ++代碼行為,不確定它是編譯器錯誤還是我的代碼的未定義/未指定的行為。 這是代碼:
#include <unistd.h>
#include <iostream>
#include <thread>
struct Parent {
std::thread t;
static void entry(Parent* p) {
p->init();
p->fini();
}
virtual ~Parent() { t.join(); }
void start() { t = std::thread{entry, this}; }
virtual void init() { std::cout << "Parent::init()" << std::endl; }
virtual void fini() { std::cout << "Parent::fini()" << std::endl; }
};
struct Child : public Parent {
virtual void init() override { std::cout << "Child::init()" << std::endl; }
virtual void fini() override { std::cout << "Child::fini()" << std::endl; }
};
int main() {
Child c;
c.start();
sleep(1); // <========== here is it
return 0;
}
代碼的輸出如下,這並不奇怪:
Child::init()
Child::fini()
但是,如果函數調用“sleep(1)”被注釋掉,輸出將是:
Parent::init()
Parent::~fini()
在Ubuntu 15.04上測試,gcc-4.9.2和clang-3.6.0都表現出相同的行為。 編譯器選項:
g++/clang++ test.cpp -std=c++11 -pthread
它看起來像一個競爭條件(vtable在線程開始之前沒有完全構造)。 這段代碼是不正確的嗎? 編譯器錯誤? 或者它應該是這樣的?
這是常見的設計問題; 你試圖做的是一個經典的反模式。
Parent
不能同時是一個線程管理器,啟動一個線程並等待線程終止:
virtual ~Parent() { t.join(); }
void start() { t = std::thread{entry, this}; }
還有一個線程對象:
virtual void init() { std::cout << "Parent::init()" << std::endl; }
virtual void fini() { std::cout << "Parent::fini()" << std::endl; }
這是兩個截然不同的概念,具有嚴格不兼容的規范。
(並且線程對象通常沒用。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.