-1

我正在制作一些回调系统,我想知道我是否可以保留函数引用,unordered_map以便以后可以调用它。

float func_imp(float x)
{
    return x;
}
int main()
{
    using Tumap = unordered_map<int, float(&)(float)>;
    Tumap umap;
    umap.emplace(0, func_imp);
    (umap[0])(10.1); //a reference type cannot be value-initialized

    using Tvec = vector<float(&)(float)>;
    Tvec uvec; // pointer to reference is illegal
    //uvec.emplace_back(func_imp);
}

是否可以使用这种类型的容器来保留回调函数?如果不是,它是使用函数指针的唯一方法吗?

4

2 回答 2

2

无论这是否是您应该做的事情(您的问题下的评论已经涵盖了这一点),仍然值得按原样回答您的问题。

地图类型的[]操作员是名副其实的瑞士军刀。你可以用它做很多事情。

  • 您可以分配一个值。
  • 您可以查找该值。
  • 您可以查找一个值,即使它尚不存在。

因此,使用该运算符对地图中存储的任何类型都有一些要求。在这种特定情况下,您遇到了它必须是值可初始化的要求,而引用不能。

顺便说一句,这也适用于常规引用,而不仅仅是函数引用。

所以答案是:只要您不使用地图的任何需要引用来执行不允许的操作的功能,您就可以在地图中尽可能多地存储引用。

在这种情况下,您可以使用umap.at(0)(10.1);. []和之间的最大区别之一at()是,如果尚未设置键,at()将抛出异常而不是创建值初始化值。

于 2021-01-19T04:20:54.507 回答
1

是否可以使用这种类型的容器来...

不管这句话如何继续:不,不可能使用这种类型的容器。具体可以参考无标准容器的元素类型。引用类型不满足容器对其元素类型的要求(至少在使用标准分配器时不满足)。

如果不是,它是使用函数指针的唯一方法吗?

不,函数指针不是唯一的方法,但它是一种有效的方法。

其他替代方法是函数对象,例如擦除函数包装器(例如std::function)或引用包装器(例如std::reference_wrapper.

我只是认为没有必要取消引用。

如果您的意思是语法上的,那么我有一个好消息,让您的关注无关紧要:无需通过指向函数的指针显式间接。间接是隐式的,就像函数引用一样。它们的调用语法是相同的例子:

float(&ref)(float) = func_imp;
float(*ptr)(float) = func_imp;
ref(42.);
ptr(42.);

因此,您不必担心。

如果您在谈论必须在运行时以性能为代价间接通过指针,我有一个坏消息让您的担忧无关紧要:引用也是一种间接形式,就像指针一样。它们(通常)不是优化。

于 2021-01-19T04:43:42.740 回答