C ++将多个对象传递给线程中的函数

Posted

技术标签:

【中文标题】C ++将多个对象传递给线程中的函数【英文标题】:C++ Passing multiple objects to a function in threads 【发布时间】:2019-11-12 10:45:54 【问题描述】:

我在线程化和将同一类的多个对象传递给函数时遇到问题。它是一个外部函数,我想在其中对每个传递的对象调用一个类方法。 我尝试传递一个对象向量以及一个指针向量。我也尝试过通过引用传递它们。

请指定,我有一个“Gas”类,其中 3 个对象是在前面的代码中构造的。我之前在线程中调用了很多方法,所以我猜这个类没有问题。 编译器返回很长的错误,带有 _M_invoke(_Index_tuple<_indices...>):

    .In file included from C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/thread:39:0,
                 from ./src/../input.h:22,
                 from ./src/mass_source.cpp:12:
C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/functional: In instantiation of 'struct std::_Bind_simple<void (*(int, std::reference_wrapper<std::vector<Ref::Gas> >))(int, std::vector<Ref::Gas>&)>':
C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/thread:142:59:   required from 'std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(int, std::vector<Ref::Gas>&); _Args = int&, std::reference_wrapper<std::vector<Ref::Gas, std::allocator<Ref::Gas> > >]'
./src/mass_source.cpp:86:50:   required from here
C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/functional:1505:61: error: no type named 'type' in 'class std::result_of<void (*(int,  std::reference_wrapper<std::vector<Ref::Gas> >))(int, std::vector<Ref::Gas>&)>'
       typedef typename result_of<_Callable(_Args...)>::type result_type;
                                                             ^
C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/functional:1526:9: error: no type named 'type' in 'class std::result_of<void (*(int, std::reference_wrapper<std::vector<Ref::Gas> >))(int, std::vector<Ref::Gas>&)>'
         _M_invoke(_Index_tuple<_Indices...>)

错误消息来自我的“原始”代码,其中我已注释掉所有行,这些行未在下面显示。据报道令人困惑,这里有一个解释:

from ./src/../input.h:22 - inclusion of thread library
from ./src/mass_source.cpp:12: - inclusion of the above input.h file
./src/mass_source.cpp:86: - calc_ms fucntion call

下面附上类声明:

namespace Ref
class Gas
    public:
        Gas(const int id, const int& imax, const int& jmax)
            id_ = id;
            NX_ = imax;
            NR_ = jmax;
        
        void set_ms(int m, double& mass_source)
            ms_[m] = mass_source;
        


    private:
           int id_;
           int NX_, NR_;
           std::vector<double> ms_;
;
 //end of namespace

调用我遇到问题的函数的代码(包括 Gas 对象及其指针的创建):

using namespace Ref;
void calc_ms(int m, std::vector<Gas>& GAS);

int main()     
    int i;
    std::vector<Gas> gases;
    std::vector<Gas*> ptr_gas(3);

    for(i = 0; i < 3; i++)                                     
        gases.push_back(Gas(i, grid));
    

    for(i = 0; i < 3; i++)                                     
        ptr_gas[i] = &gases[i];
    
    std::vector<std::thread*> th_gas;
    for(i = 0; i < 20; i++)
        std::thread *thr = new std::thread(calc_ms, i, std::ref(gases));
        th_gas.push_back(thr);
    
    for(auto &X : th_gas)
        X->join();
        delete X;
    
    th_gas.clear();

还有calc_ms函数定义:

using namespace Ref;
void calc_ms(int m, std::vector<Gas>& GAS)
    double MassSourceCH4 = .... ;
    double MassSourceCO = .... ;
    double MassSourceCO2 = .... ;

    GAS[0].set_ms(m, MassSourceCH4);
    GAS[1].set_ms(m, MassSourceCO);
    GAS[2].set_ms(m, MassSourceCO2);


我也尝试过通过拷贝传递gas,并将ptr_gas作为参考和拷贝。

注释:Gas 类的 ms_ 成员在代码中的其他位置调整了大小,因此使用索引的分配不是问题。

【问题讨论】:

在main函数的文件中。你知道如何帮助我,或者你只是试图证明我什么都不知道? 那么你为什么不展示我们呢?这需要成为minimal reproducible example 的一部分。再一次,哪一行是源文件mass_source.cpp 的第 86 行?一个好的minimal reproducible example 应该是复制您所询问的问题的最小可能程序,并且为了使其完美,我们应该能够复制粘贴它并自己复制问题,而不需要我们编写任何额外的代码。 更好,now with quite some editing I can build it。但不要复制你得到的错误。哪种表示错误的来源不在您显示的代码中。 如果我将std::ref 更改为std::cref,我设法有点replicate the error。请检查您不使用的实际代码std::cref 感谢您的努力。我检查了,不幸的是它是 std::ref ...我会尝试安装其他编译器。也许这就是问题所在...... 【参考方案1】:

这是一个简化版本,展示了如何正确使用线程以及如何通过引用将向量传递给线程:

class Gas  /*...*/ ;

void calc_ms(int m, std::vector<Gas>& gases);

int main() 
    std::vector<Gas> gases;
    std::vector<std::thread> th_gas;
    for(int i = 0; i < 20; ++i)
        th_gas.emplace_back(calc_ms, i, std::ref(gases));
    for(auto& t : th_gas)
        t.join();
    th_gas.clear();

【讨论】:

@Padzak 在那种情况下,我怀疑任何事情都会发生。 嗯,问题不在于线程本身,而在于将对象向量传递给被调用函数 @Padzak 这个例子通过引用将向量传递给calc_ms。你真的应该认真对待,否则你将无济于事。 什么意思?我想通过引用传递它。 @Padzak 我冒着重复自己的风险:这个例子通过引用将向量传递给calc_ms

以上是关于C ++将多个对象传递给线程中的函数的主要内容,如果未能解决你的问题,请参考以下文章

将多个参数传递给线程函数

Java 多线程实现多个窗口同时卖票

为啥threading.thread将空字典传递给python中的函数线程

通过指针将堆栈分配的对象传递给在另一个线程上执行的函数

多线程篇五:多个线程访问共享对象和数据的方式

C ++ 0x中的线程析构函数与boost