Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/139.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;11线程编译错误,删除了复制构造函数和std::thread,为什么?_C++_C++11 - Fatal编程技术网

C++ C++;11线程编译错误,删除了复制构造函数和std::thread,为什么?

C++ C++;11线程编译错误,删除了复制构造函数和std::thread,为什么?,c++,c++11,C++,C++11,这会发出大约100行错误。错误:使用了run_me copy构造函数的deleted函数等。 那么,这里有什么问题 #include<thread> #include<iostream> #include<vector> #include<fstream> #include<string> #include<chrono> using namespace std; //creating thread to print l

这会发出大约100行错误。错误:使用了run_me copy构造函数的deleted函数等。 那么,这里有什么问题

#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;
}
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
//创建从文件打印行的线程
班主任{
IFFS;
公众:
字符串s;
运行_me():fs(“lliftOff.cpp”,ifstream::in){}
void运算符()(){

cout您的
ifstream
实现缺少对移动操作的支持,仍在删除复制操作

您可以使用lambda延迟线程内的run\u me创建

std::thread t { [] { run_me{}(); } };
如果希望在线程开始之前保持运行创建,可以使用
std::ref

run_me rm;
thread t1{ []( run_me & rm ) { rm(); }, std::ref(rm) };

解释

标准要求传递给
std::thread
的相关构造函数的对象和参数必须是
MoveConstructible

给定代码的问题是
类run\u me
有一个隐式删除的复制/移动构造函数,因为它有一个不可复制的成员;
std::ifstream fs


解决方案#1-更改通话地点

为了防止编译器试图复制
类run_me
,我们所要做的就是将对象包装在lambda中,并使用所述对象初始化
std::thread

std::thread t1 {
  [] { run_me {} (); }
};
注意:上面创建了一个临时的
run_me{}
并在匿名lambda内部对其调用
operator()
,临时的
run me{}
将在实际调用lambda函数时创建,而不是在创建lambda时。当
t1
调用
匿名lambda()
将输入功能范围,并初始化
运行{}


解决方案#2-更改
类运行我

通常我们只需向
类run\u me
添加一个move构造函数,该构造函数将使用原始
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();
    }
};
#包括
#包括
#包括
#包括
班主任{
std::唯一的ptr fs;
公众:
字符串s;
快跑
:fs(新的std::ifstream(“foo.cpp”,ifstream::in))
{ }
run_me(run_me&&src)
:fs(标准::移动(src.fs))
{ }
void运算符()(){
while(getline(*fs,s)){

coutFile streams会自动关闭。不需要析构函数。istream不可复制。因此我猜默认的复制构造函数正在尝试复制ifstream。有一个输入错误,它是
libstdc++
not
stdlibc++
@user2485710。修复了,供将来参考,您可以通过编辑有问题的帖子来自己修复此类输入错误。有人知道吗请详细说明如何使用lambda函数延迟创建对象。它是如何工作的?std::thread t1{[]{run_me{}();};@vivek请参阅解决方案#1中的修改注释。@vivek它相当于
run_me temporary_variable={};temporary_variable()
,即:首先默认初始化一个临时的
运行me
,然后在此临时对象上调用
操作符()
。我认为您实际上不需要解决方案中的lambda。如果包装对象是可调用的,则“std::ref”返回的“std::reference包装器”已可调用。