[英]C++11 thread compilation error, deleted copy constructor and std::thread, why?
這會發出大約100行錯誤。 錯誤:使用run_me復制構造函數的已刪除函數等。 那么,這里的問題是什么?
#include<thread>
#include<iostream>
#include<vector>
#include<fstream>
#include<string>
#include<chrono>
using namespace std;
//creating thread to print line from file
class run_me {
ifstream fs;
public:
string s;
run_me(): fs("lliftOff.cpp",ifstream::in) {}
void operator()(){
cout<<"hi";
while(getline(fs,s) ) {
cout<<s<<endl;
this_thread::sleep_for (chrono::seconds(1));
}
}
~run_me() {
fs.close();
}
};
int main() {
thread t1{run_me()};
t1.join();
cout<<"shutting down now"<<endl;
}
你的ifstream
實現不支持移動操作,仍然刪除復制操作。
您可以使用lambda來延遲線程內的run_me創建
std::thread t { [] { run_me{}(); } };
如果要在線程啟動之前保留run_me創建,可以使用std::ref
run_me rm;
thread t1{ []( run_me & rm ) { rm(); }, std::ref(rm) };
說明
標准要求傳遞給std::thread
的相關構造函數的對象和參數必須是MoveConstructible
。
給定代碼的問題是class run_me
有一個隱式刪除的 copy / move-constructor,因為它有一個不可復制的成員; std::ifstream fs
。
解決方案#1 - 更改呼叫站點
為了防止編譯器嘗試復制class run_me
我們所要做的就是將對象包裝在lambda中並用這個對象初始化我們的std::thread
:
std::thread t1 {
[] { run_me {} (); }
};
注意:上面創建了一個臨時的run_me {}
並在匿名lambda中調用了operator()
,當實際調用lambdas函數時,將創建臨時run me {}
,而不是在創建lambda時。 當t1
調用anonymous-lambda ()
,將輸入函數作用域,並初始化run_me {}
。
解決方案#2 - CHANGE class run me
通常我們只是將一個move-constructor添加到class run_me
,它將使用原始fs
的std::move
d實例初始化fs
,這不是一個大問題。
遺憾的是,諸如libstdc++
實現還沒有實現正確移動流所需的功能 ,這意味着我們無法移動標准庫流。
如果您正在使用libstdc++
或缺少可移動流的任何其他實現,我們將不得不在編寫我們的解決方案時采取某種方式,我建議如下:
#include <iostream>
#include <fstream>
#include <string>
#include <memory>
class run_me {
std::unique_ptr<std::ifstream> fs;
public:
string s;
run_me()
: fs (new std::ifstream ("foo.cpp",ifstream::in))
{ }
run_me (run_me&& src)
: fs (std::move (src.fs))
{ }
void operator()() {
while(getline(*fs,s) ) {
cout<<s<<endl;
this_thread::sleep_for (chrono::seconds(1));
}
}
~run_me() {
if (fs) // if we haven't been moved-from
fs->close();
}
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.