将对虚拟类实现的引用作为线程参数传递

时间:2014-12-01 15:33:38

标签: c++ c++11 reference virtual-inheritance stdthread

我需要你的帮助,使std::thread与模板化对象一起工作。这次我的问题出现在其中一个论点中。

我尝试将对虚拟类的(有效)实例化的引用作为我的线程的参数之一传递,并且它不起作用。请注意,传递指针而不是引用可以解决所有问题。但是,为什么我不能提供参考(我更喜欢,出于多种原因)

重复我的错误的小代码:

#include <cstdio>
#include <thread>
#include <vector>

template<typename T>
class functor { public: virtual T operator()(T) const = 0; };

template<typename T>
class square : public functor<T>
{
    public:
        T operator()(T f) const { return f*f; }
};

template<typename T>
void thread(const functor<T>& func, size_t imin, size_t imax) // line1
{
    for(size_t i=imin; i<imax; ++i)
    {
        T arg = T(i);
        std::cout << arg << "=>" << (func)(arg)) << std::endl; // line2
    }
}

template<typename T>
void threadlauncher(const functor<T>& func, size_t imin, size_t imax, size_t nbthread)
{
    size_t window = (imax-imin)/nbthread + ((imax-imin)%nbthread?1:0);
    std::vector<std::thread> threads;
    for (size_t idthread=0; idthread<nbthread; ++idthread)
    {
        size_t tmin = std::min(window*(idthread+0), imax);
        size_t tmax = std::min(window*(idthread+1), imax);
        threads.push_back(
            std::thread(&thread<T>, func, tmin, tmax) // line3
        );
    }
    for (std::thread& thread : threads)
        thread.join();
}
int main()
{
    square<float> func;
    threadlauncher<float>(func, 0, 10, 3);
    return 0;
}

编译器(gcc 4.9.2)告诉我,我的对象无效,因为operator()中的threadlauncher是虚拟的

请注意,更改代码以使用指针传递线程的参数可以解决此问题

void thread(const functor<T>* func, size_t imin, size_t imax) // line1
std::cout << arg << "=>" << (*func)(arg)) << std::endl; // line2
std::thread(&thread<T>, &func, tmin, tmax) // line3

如何让他了解我的参考资料有效?

修改

我从编译器收到一条长/不可重复的错误消息。我想重要的部分是

src/functorthreads.cc:50:38:   required from here
/usr/include/c++/4.9.2/functional:1713:9: erreur: invalid abstract parameter type ‘functor<float>’
         __type;
         ^
src/functorthreads.cc:6:7: note:   because the following virtual functions are pure within ‘functor<float>’:
 class functor
       ^
src/functorthreads.cc:9:13: note:   T functor<T>::operator()(T) const [with T = float]
   virtual T operator()(T) const = 0;

1 个答案:

答案 0 :(得分:1)

std::thread获取其参数的副本。函数的参数是引用并不重要.... thread构造函数仍将复制参数,因为它们被传递给另一个线程。这就是指针的工作原理,因为它们被复制了。

如果您知道您的对象在整个生命周期内都会保留在范围内,您可以使用std::ref来包装您的参数:

std::thread(&thread<T>, std::ref(func), tmin, tmax)