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

Error about std::promise in C++

本文关键字:promise 错误 std C++      更新时间:2023-10-16

我正试图将我的类实例传递到线程中,并从线程返回处理过的对象。我在谷歌上搜索过C++多线程,发现std::promise可能会有所帮助。

然而,我一开始就被卡住了。这是我的代码:

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);
}

上述代码生成一个错误:

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

我可以知道我做错了什么吗?如何解决?

非常感谢。:-)

您的第一个问题是您使用的是std::thread-std::thread是一个低级别的类,您应该在它之上构建更高的抽象。线程是C++在C++11中新标准化的,所有的粗糙部分还没有归档。

在C++11中使用线程有三种不同的模式可能对您有用。

首先,std::async。第二,std::threadstd::packaged_task混合。第三,对std::threadstd::promise进行了原始处理。

我将说明第三个,它是最低级别和最危险的,因为这就是你所要求的。我建议考虑前两种选择。

#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";
  }
}

实例

使用std::async,您将有一个返回DataWareHouse的函数,它将直接返回一个std::future<DataWareHouse>

有了std::packaged_task<>,它将把你的run_thread变成一个可以执行的packaged_task,并从中提取一个std::future

std::promise<>是不可复制的,在调用run_thread()时,您隐含地试图调用复制构造函数。错误消息告诉您不能使用复制构造函数,因为它被标记为private。

您需要通过引用传递承诺(std::promise<DataWareHouse> &)。如果保证callerFunc()run_thread()处理完对象之前不会返回,那么这是安全的(否则,您将使用对已销毁的堆栈分配对象的引用,我不必解释为什么这很糟糕)。

您正试图通过值将promise传递给线程;但是您需要通过引用传递,以便将结果返回给调用者的promise。std::promise是不可复制的,以防止这种错误。

std::thread(&run_thread,std::ref(data_chunks));
                        ^^^^^^^^
void run_thread(std::promise<DataWareHouse> & data_chunks)
                                            ^

错误告诉您不能复制std::promise,您可以在这里执行:

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

这里:

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

你应该通过一个参考:

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

然后将std::reference_wrapper传递给线程,否则它也将尝试复制promise。使用std::ref:很容易做到这一点

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

显然,data_chunks必须是活动的,直到线程完成运行,所以您必须在callerFunc()中加入线程。