簡體   English   中英

C ++多線程程序嘗試使用已刪除的功能

[英]C++ multithread program attempts to use deleted function

我是C ++多線程程序領域的新手。 我想從磁盤上讀取塊數據並根據這些數據進行一些計算。 為了簡化代碼,我編寫了以下演示來測試我的想法。 但是,我發現了一些問題。

#include <iostream>
#include <thread>
#include <string>
#include <mutex>
#include <vector>
#include <condition_variable>

std::condition_variable cv;
std::mutex cv_m;

bool is_print;

void read_value(std::vector<int> &data)
{
    for (int j = 1; j < 5; j++)
    {
        std::cout << "read data iteration is " << j << std::endl;
        std::lock_guard<std::mutex> lk(cv_m);
        for (int i = 0; i < 5; i++)
            data.at(i) = i * j;
        is_print = true;
        cv.notify_one();
    }
}

void print_value(const std::vector<int> &data)
{
    std::cout << "output data" << std::endl;
    std::unique_lock<std::mutex> lk(cv_m);
    cv.wait(lk, []{return is_print;});
    for (int i = 0; i < data.size(); i++)
        std::cout << data[i] << std::endl;
    is_print = false;
}

int main()
{
    is_print = false;
    std::vector<int> data = {0, 0, 0, 0, 0};

    std::thread thread_read(read_value, data);
    std::thread thread_print(print_value, data);

    thread_print.join();
    thread_read.join();

    return 0;
}

在此演示中,我使用“ read_value”來模擬從磁盤讀取數據,並且希望多次從磁盤讀取數據。 因此,我在函數“ read_value”中添加了一個外循環。 之后,我使用“ print_value”功能輸出數據。 但是,在這種情況下,我遇到以下錯誤,這表明我使用了已刪除的函數。 我不確定是什么問題以及如何多次讀取數據。 非常感謝!

In file included from 

/Users/zsk/Downloads/programming/C++/multi_thread/multi_thread/main.cpp:10:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/thread:342:5: error: attempt to use a deleted function
    __invoke(_VSTD::move(_VSTD::get<1>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...);
    ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/thread:352:5: note: in instantiation of function template specialization 'std::__1::__thread_execute<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, void (*)(std::__1::vector<int, std::__1::allocator<int> > &), std::__1::vector<int, std::__1::allocator<int> > , 2>' requested here
    __thread_execute(*__p, _Index());
    ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/thread:368:47: note: in instantiation of function template specialization 'std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, void (*)(std::__1::vector<int, std::__1::allocator<int> > &), std::__1::vector<int, std::__1::allocator<int> > > >' requested here
    int __ec = __libcpp_thread_create(&__t_, &__thread_proxy<_Gp>, __p.get());
                                              ^
/Users/zsk/Downloads/programming/C++/multi_thread/multi_thread/main.cpp:51:17: note: in instantiation of function template specialization 'std::__1::thread::thread<void (&)(std::__1::vector<int, std::__1::allocator<int> > &), std::__1::vector<int, std::__1::allocator<int> > &, void>' requested here
    std::thread thread_read(read_value, data);

問題在於std::thread對象需要能夠復制您傳遞給線程的參數。 並且引用不能被復制。

為了解決這個問題,您需要使用std::refstd::cref來包裝參數:

std::thread thread_read(read_value, std::ref(data));
std::thread thread_print(print_value, std::cref(data));

如果您嘗試使用引用,則使用線程是令人驚訝的。 另一個答案是完全正確的,請使用std::ref傳遞參數。

我個人更喜歡使用lambda:

std::thread thread_read([&data](){ read_value(data); });
std::thread thread_print([&data = std::as_const(data)](){ print_value(data); });

它可能不如std::ref優雅,盡管它使用了您在所有其他地方都已經知道的概念,而不是要求您記住意外的復制。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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