简体   繁体   English

关于C ++中std :: promise的错误

[英]Error about std::promise in C++

I am trying to pass my class instance into threads and the return the processed objects from threads. 我试图将我的类实例传递给线程,并从线程返回处理后的对象。 I've googled about C++ multithreading, and found that std::promising can be helpful. 我搜索了C ++多线程,发现std :: promising可能会有所帮助。

However, I am stuck at the very beginning. 但是,我一开始就陷入困境。 Here is my code: 这是我的代码:

void callerFunc()
{
    //...
    std::promise<DataWareHouse> data_chunks;    
    // DataWareHouse is my customized class
    //data_chunks has a vector<vector<double>> member variable
    std::thread(&run_thread,data_chunks);
    // ............
}

void run_thread(std::promise<DataWareHouse> data_chunks)
{
    // ... 
    vector<vector<double>> results;
    // ...
    data_chunks.set_value(results);
}

The above code generates an error: 上面的代码生成错误:

 `error C2248: 'std::promise<_Ty>::promise' : cannot access private member declared in class 'std::promise<_Ty>'`

May I know what am I wrong and how to fix it? 我可以知道我在做什么以及如何解决吗?

Many thanks. 非常感谢。 :-) :-)

Your first problem is that you are using std::thread -- std::thread is a low level class which you should build higher abstractions up on. 您的第一个问题是您正在使用std::thread - std::thread是一个低级类,应在其上构建更高的抽象。 Threading is newly standardized in C++ in C++11, and all of the rough parts are not filed off yet. 线程在C ++ 11中的C ++中是新标准化的,并且所有粗略部分都尚未提出。

There are three different patterns for using threading in C++11 that might be useful to you. 在C ++ 11中使用线程的三种不同模式可能对您有用。

First, std::async . 首先, std::async Second, std::thread mixed with std::packaged_task . 其次, std::threadstd::packaged_task混合。 And third, dealing with std::thread and std::promise in the raw. 第三,处理原始的std::threadstd::promise

I'll illustrate the third, which is the lowest level and most dangerous, because that is what you asked for. 我将说明第三个级别,它是最低级别和最危险的级别,因为这是您所要求的。 I would advise looking at the first two options. 我建议您看一下前两个选项。

#include <future>
#include <vector>
#include <iostream>

typedef std::vector<double> DataWareHouse;

void run_thread(std::promise<DataWareHouse> data_chunks)
{
  DataWareHouse results;
  results.push_back( 3.14159 );
  data_chunks.set_value(results);
}

std::future<DataWareHouse> do_async_work()
{
  std::promise<DataWareHouse> data_chunks;  
  std::future<DataWareHouse> retval = data_chunks.get_future();
  // DataWareHouse is my customized class
  //data_chunks has a vector<vector<double>> member variable
  std::thread t = std::thread(&run_thread,std::move(data_chunks));
  t.detach(); // do this or seg fault
  return retval;
}

int main() {
  std::future<DataWareHouse> result = do_async_work();
  DataWareHouse vec = result.get(); // block and get the data
  for (double d: vec) {
    std::cout << d << "\n";
  }
}

Live example 现场例子

With std::async , you'd have a function returning DataWareHouse , and it would return a std::future<DataWareHouse> directly. 使用std::async ,您将具有一个返回DataWareHouse的函数,它将直接返回std::future<DataWareHouse>

With std::packaged_task<> , it would take your run_thread and turn it into a packaged_task that can be executed, and a std::future extracted from it. 使用std::packaged_task<> ,它将占用您的run_thread并将其转换为可以执行的packaged_task ,并从中提取std::future

std::promise<> is not copyable, and in calling run_thread() you are implicitly trying to invoke the copy constructor. std::promise<>是不可复制的,并且在调用run_thread()您隐式地尝试调用复制构造函数。 The error message is telling you that you cannot use the copy constructor since it is marked private. 该错误消息告诉您,由于标记为私有,因此无法使用复制构造函数。

You need to pass a promise by reference ( std::promise<DataWareHouse> & ). 您需要通过引用传递一个承诺( std::promise<DataWareHouse> & )。 This is safe if callerFunc() is guaranteed not to return until run_thread() is finished with the object (otherwise you will be using a reference to a destroyed stack-allocated object, and I don't have to explain why that's bad). 如果这是安全的callerFunc()保证不会返回,直到run_thread()完成与对象(否则你将使用到销毁堆栈分配对象的引用,而我也没有解释为什么这是很糟糕)。

You're trying to pass the promise to the thread by value; 您正在尝试通过值将承诺传递给线程; but you need to pass by reference to get the results back to the caller's promise. 但是您需要通过引用传递结果,以将结果返回给呼叫者的承诺。 std::promise is uncopyable, to prevent this mistake. std::promise无法复制,以防止发生此错误。

std::thread(&run_thread,std::ref(data_chunks));
                        ^^^^^^^^

void run_thread(std::promise<DataWareHouse> & data_chunks)
                                            ^

The error is telling you you cannot copy an std::promise , which you do here: 错误提示您无法复制std::promise ,您可以在此处执行以下操作:

void run_thread(std::promise<DataWareHouse> data_chunks)

and here: 和这里:

std::thread(&run_thread,data_chunks); // makes copy of data_chunks

You should pass a reference: 您应该传递参考:

void run_thread(std::promise<DataWareHouse>& data_chunks);
//                                         ^

And then pass an std::reference_wrapper to the thread, otherwise it too will attempt to copy the promise. 然后将std::reference_wrapper传递给线程,否则它也会尝试复制promise。 This is easily done with std::ref : 这可以通过std::ref轻松完成:

std::thread(&run_thread, std::ref(data_chunks));
//                       ^^^^^^^^

Obviously data_chunks must be alive until the thread finished running, so you will have to join the thread in callerFunc() . 显然,在线程完成运行之前, data_chunks必须处于活动状态,因此您必须在callerFunc()加入线程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM