簡體   English   中英

C ++ 11線程編譯錯誤,刪除了復制構造函數和std :: thread,為什么?

[英]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 ,它將使用原始fsstd::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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM