C++ 模板 - 可变参数模板和通过 const 引用传递

标签 c++ c++11 pass-by-reference variadic-templates

我有一个带有 enqueue 函数的 ThreadPool 类:

class ThreadPool
{
public:
    //(Code removed here)

    template <typename ... Args, typename Fun>
    JobId enqueue(Fun func, Args ... args);

    //(Code removed here)
}

我在 Object 类的这些非静态成员函数 loadStuff 上使用它:

class Object
{
    //(Code removed here)
    void init(const PrepareData & prepareData);
    virtual bool loadStuff(const PrepareData & prepareData);
    //(Code removed here)
}

通过调用 QObject::init :

void QObject::init(const PrepareData &prepareData)
{
    threadPool->enqueue(&loadStuff, this, prepareData);
}

但我注意到 prepareData 是通过拷贝传递的,这会消耗大量内存并显着降低程序速度(并且无用)。

所以我删除了PrepareData中的copy ctor和assignment operator。该程序不再编译,因为可变参数模板按值而不是按引用获取其参数。

所以我声明 enqueue 通过引用传递可变模板参数:

template <typename ... Args, typename Fun>
JobId enqueue(Fun func, Args&... args);

现在不再调用复制构造函数,但我得到以下错误:

object.cpp:21: error: no matching function for call to

'ThreadPool::enqueue(bool (Object::*)(const PrepareData&), Object *, const PrepareData&)' threadPool->enqueue(&prepareType, this, loadStuff);

所以我完全不知道如何做到这一点。我可以不传递 const PrepareData &,而是通过拷贝传递 const PrepareData *,但我想了解为什么它不适用于 const 引用。

最佳答案

这个:

template <typename ... Args, typename Fun>
JobId enqueue(Fun func, Args ... args);

复制所有 args 因为它们都是按值传递的。参数传递的工作方式似乎有些困惑——调用 enqueue 并引用 const 并不重要,重要的是 enqueue 接受它的参数按值(value)。 init() 是按引用传递的,但 enqueue() 不是。

您可能想要的是将引用包装器传递给您的数据(按值):

threadPool->enqueue(&loadStuff, this, std::ref(prepareData));

这将避免复制 prepareData 并正确调用 loadStuff()。这也让 enqueue() 的调用者有责任知道应该复制哪些内容以及应该引用哪些内容。


尽管如此,QObject 需要确保prepareData 持续足够长的时间。我们通过引用 const 来获取它,所以它似乎没有任何方法可以做到这一点。因此,也许另一种方法是让 init() 按值获取其数据:

void QObject::init(PrepareData prepareData)
{
    threadPool->enqueue(&loadStuff, this, std::move(prepareData));
}

关于C++ 模板 - 可变参数模板和通过 const 引用传递,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37730989/

相关文章:

c# - 在 C++ 中,我可以有一个函数/方法通过引用传递一个参数,而一个重载通过值传递它吗?

c++ - 类型的类型与模板?

c++ - 有没有办法从 C++ 中的枚举类中获取随机数?

c++ - 为什么 std::stoi 和 std::array 不能用 g++ c++11 编译?

c++ - 智能指针+循环+ "->"

javascript - 镜像 Javascript 变量更改

c++ - 为什么这个重载函数的调用不明确?

c++ - 使用 _beginthreadx 将结构传递给线程

c++ - 关于锁的 std::atomic 实现能否将程序的行为从正确更改为不正确?

PHP 数组引用;将引用保存在数组中供以后使用