C++11 线程:将向量传递给线程函数时出错

Posted

技术标签:

【中文标题】C++11 线程:将向量传递给线程函数时出错【英文标题】:C++11 Threads: Error passing a vector to a thread function 【发布时间】:2014-04-24 10:48:47 【问题描述】:

作为一个更大项目的一部分,我正在研究多线程中值函数。我几乎没有 C++ 经验。下面的中值函数应采用 3 维 int 向量的向量,并返回一个 3 维 int 向量,其中每个条目是输入向量中该索引中所有条目的中值。所以如果输入是,,>,则返回。此代码将用于实现用于实时视频的中值模糊,因此需要多线程。

#include <thread>
#include <iostream>
#include <mutex>
#include <vector>
#include <algorithm>
#include "median.h"

// mutex to protect bgrPixel (possibly not needed)
std::mutex mtx;


std::vector<int> median(const std::vector<std::vector<int> >& input)

    std::vector<int> bgrPixel;              // Vector to store median BGR value
    std::thread first(thread_function, bgrPixel, input, 0); // thread for each colour channel
    std::thread second(thread_function, bgrPixel, input, 1);
    std::thread third(thread_function, bgrPixel, input, 2);
    first.join();
    second.join();
    third.join(); 
    return bgrPixel;


void thread_function(std::vector<int>& bgrPixel, const std::vector<std::vector<int> >&                 input1, int channel)


    std::vector<int> input = input1[channel];  // copy the colour channel
    std::sort(input.begin(), input.end());
    int size = input.size();
    if (size %2 == 0)   // get the median
    
        mtx.lock();
        bgrPixel[channel] = (input[size/2] + input[size/2 + 1])/2;
        mtx.unlock();
     else
    
        mtx.lock();
        bgrPixel[channel] = input[(size-1)/2];
        mtx.unlock();
    

我遇到的问题是,在编译时,g++(还有 clang)给出了一个相当难以理解的错误:

 g++ -std=c++11 -pthread -o median median.cpp

 In file included from /usr/include/c++/4.8.2/thread:39:0,
                  from median.cpp:1:
 /usr/include/c++/4.8.2/functional: In instantiation of ‘struct std::_Bind_simple<void           (*(std::vector<int>, std::vector<std::vector<int> >, int))(std::vector<int>&, const      std::vector<std::vector<int> >&, int)>’:
 /usr/include/c++/4.8.2/thread:137:47:   required from ‘std::thread::thread(_Callable&&,           _Args&& ...) [with _Callable = void (&)(std::vector<int>&, const      std::vector<std::vector<int> >&, int); _Args = std::vector<int, std::allocator<int> >&,      const std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int,      std::allocator<int> > > >&, int]’
 median.cpp:15:58:   required from here
 /usr/include/c++/4.8.2/functional:1697:61: error: no type named ‘type’ in ‘class                std::result_of<void (*(std::vector<int>, std::vector<std::vector<int> >, int))     (std::vector<int>&, const std::vector<std::vector<int> >&, int)>’
        typedef typename result_of<_Callable(_Args...)>::type result_type;
                                                         ^
 /usr/include/c++/4.8.2/functional:1727:9: error: no type named ‘type’ in ‘class      std::result_of<void (*(std::vector<int>, std::vector<std::vector<int> >, int))     (std::vector<int>&, const std::vector<std::vector<int> >&, int)>’
          _M_invoke(_Index_tuple<_Indices...>)
          ^

我发现了类似的错误消息c++11 Thread class how to use a class member function,但它并没有专门处理我的问题。 任何帮助将不胜感激,我完全希望这是因为我不知道我在做什么:P

编辑:thread_function 和 median 的原型包含在头文件 median.h 中。

【问题讨论】:

当你得到这个来编译你有一个更狡猾的问题:你的bgrPixel向量不包含三个项目,所以当你做bgrPixel[channel] = ...你有undefined behavior。这可以通过说向量在声明中包含三个项目来轻松解决:std::vector&lt;int&gt; bgrPixel(3); 由于您的向量大小为 3,您可以将 std::vector&lt;int&gt; 替换为 std::array&lt;int, 3&gt;。那将不太容易出错。我没有 g++ 编译器,但它适用于 VC++。你的编译器可能有问题。 您不需要互斥锁来防止同时访问bgrPixel:每个线程都访问一个不同的元素 - channel 每个线程都是不同的 - 并且对不同容器元素的访问是不冲突。 【参考方案1】:

替换

std::thread first(thread_function, bgrPixel, input, 0);

std::thread first(thread_function, std::ref(bgrPixel), std::ref(input), 0);

现场示例:http://coliru.stacked-crooked.com/a/630775aafc3d4642

【讨论】:

谢谢!这完美!我还发现,如果我根本不使用引用,它就会编译。我需要阅读参考资料。 经过测试,似乎当主线程认为该变量是不必要的时,它可能会被删除,您可能会读取一些“随机”信息而不是您期望的信息。所以我想如果你真的不需要的话,不通过引用传递会更安全。

以上是关于C++11 线程:将向量传递给线程函数时出错的主要内容,如果未能解决你的问题,请参考以下文章

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

通过引用向量传递的线程函数启动缓慢

在函数中传递向量元素[关闭]

无法从构造函数中将数组值传递给向量

将指针向量传递给c ++中的函数[重复]

获取传递给函数的参数,使用线程返回