C++ 函数引用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/480248/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 15:34:40  来源:igfitidea点击:

Function References

c++

提问by GlobalKiller

So I was just working with function pointers and I remembered that you could do this:

所以我只是在使用函数指针,我记得你可以这样做:

void Foo()
{
}

int main()
{
    void(& func)() = Foo;

    func(); //::Foo();
}

The obvious advantage being that references reference valid objects (unless they're misused), or functions in this case.

明显的优势是引用引用有效的对象(除非它们被误用),或在这种情况下的函数。

The obvious disadvantages being that you can't store an array of references and can't use them for member function pointers (at least as far as I can tell).

明显的缺点是您不能存储引用数组,也不能将它们用于成员函数指针(至少据我所知)。

My question:does anyone use them (i.e., function references, notfunction pointers), and if so, in what scenarios have you found them useful/helpful?

我的问题:有没有人使用它们(即函数引用而不是函数指针),如果是,你在什么情况下发现它们有用/有帮助?

The only place I can see them being useful off the bat is binding a reference to a certain function when working with conditional compilation.

我能看到它们立即有用的唯一地方是在使用条件编译时将引用绑定到某个函数。

回答by Robert Gould

I've used them before to add customization to classes by passing them to the constructor in a way like the strategy pattern

我之前使用过它们通过以类似于策略模式的方式将它们传递给构造函数来为类添加自定义

回答by Johannes Schaub - litb

I think your example usage is quite good. Because if you would use an ordinary function pointer, and you then apply the address-of operator, you would get the address of the function pointer. Using a reference to function will do the expected thing, in that it returns a pointer to the function itself.

我认为您的示例用法非常好。因为如果您使用普通的函数指针,然后应用地址运算符,您将获得函数指针的地址。使用对函数的引用会做预期的事情,因为它返回一个指向函数本身的指针。

I also can't think of many examples. Keeping function references, as you point out, has some ugly consequences. Another possibly unwanted consequence is, if kept as a class-member, your objects will be non-assignable if you don't write your own operator= and refrain from trying to re-assign the function-reference.

我也想不出很多例子。正如您所指出的,保留函数引用会产生一些丑陋的后果。另一个可能不需要的后果是,如果保留为类成员,如果您不编写自己的 operator= 并避免尝试重新分配函数引用,则您的对象将是不可分配的。

I think most uses of function references are implicit, much like most uses of array-references - although much more so, when you accept arguments by-reference:

我认为函数引用的大多数用途都是隐式的,就像数组引用的大多数用途一样 - 尽管更多,当您通过引用接受参数时:

template<typename T>
void do_something(T const& t) { ... }

While accepting arrays by reference has the advantage of not losing their size information, accepting functions by reference explicitly doesn't seem to have an advantage (at least as far as I can see). I suppose the existence of function references largely is justified by the idealistic view of a reference as an alias-name of some object or function, together with the fact that it allows passing functions to such templates that accept their argument by reference.

虽然通过引用接受数组具有不丢失其大小信息的优势,但通过引用明确接受函数似乎没有优势(至少就我所见)。我认为函数引用的存在在很大程度上是通过将引用作为某个对象或函数的别名的理想主义观点来证明的,以及它允许​​将函数传递给通过引用接受其参数的模板的事实。

I would probably avoid using them if I wouldn't need them inevitably. Constant function pointers also provide non-reassignable callables, and will probably avoid confusions when other programmers, who possibly are not very familiar with this language niches, read your code. Worth to note that Vandervoorde & Josuttis also recommend to avoid them to reduce confusion (in their book C++ Templates - The Complete Guide).

如果我不会不可避免地需要它们,我可能会避免使用它们。常量函数指针还提供不可重新分配的可调用对象,并且可能会避免在其他可能不太熟悉该语言领域的程序员阅读您的代码时产生混淆。值得一提的是,Vandervoorde & Josuttis 还建议避免使用它们以减少混淆(在他们的书 C++ Templates - The Complete Guide 中)。

回答by LB--

Function references, unlike function pointers, make it harder to create them from an invalid source. This is useful if you are making a wrapper around a C library - the C++ code can take a callback function by reference and pass the pointer to the C library if the lbrary requires that the passed pointer must not be NULL.

与函数指针不同,函数引用使得从无效源创建它们变得更加困难。如果您正在围绕 C 库制作包装器,这很有用 - 如果图书馆要求传递的指针不能为 NULL,C++ 代码可以通过引用获取回调函数并将指针传递给 C 库。

It is also a convenient way to alias a function, especially in C++11 with the new auto keyword:

这也是一种给函数取别名的便捷方式,尤其是在 C++11 中使用新的 auto 关键字:

#include <iostream>
#include <typeinfo>

void f(int i, char c)
{
    std::cout << i << ' ' << c << std::endl;
}

int main()
{
    std::cout << typeid(f).name() << std::endl; //FvicE
    f(0, '1');

    void (*pf)(int, char) (&f); //ugly
    std::cout << typeid(pf).name() << std::endl; //PFvicE
    (*pf)(2, '3');
    pf(4, '5'); //works, but I don't recommend it

    void (&rf)(int, char) (f); //still ugly
    std::cout << typeid(rf).name() << std::endl; //FvicE
    rf(6, '7');

    auto &af (f); //pretty, but only works in C++11
    std::cout << typeid(af).name() << std::endl; //FvicE, same as above
    af(8, '9');
}

回答by Ichthyo

in addition to the use as strategy (as pointed out by Robert Gould), I freqently use them at the entrance point to (template) metaprogramming. A function reference can easily be picked up by a template parameter; from this point on it can be passed through several layers of (metaprogramming) templates. Of course, this holds true for a function pointer as well, but the reference is an aliasand thus communicates the intention more clearly.

除了用作策略(如 Robert Gould 所指出的)之外,我还经常在(模板)元编程的入口点使用它们。模板参数可以轻松获取函数引用;从这一点开始,它可以通过几层(元编程)模板。当然,这也适用于函数指针,但引用是一个别名,因此更清楚地传达了意图。

To give an example: when writing a generic command dispatching system for an application, a lot of different operations need to be announced as commands. We can use a simple "builder function" as front-end for the client code. Behind the scenes, this builder function picks up the actual function signature as template parameter, derives (by template metaprogramming) the actual parameter and return type values and possibly picks the suitable specialisation to store a "memento" and an "undo functor". These functors can than be stored either as function pointers internally, or using boost or tr1 or C++11 function objects. This way, it is possible to build a type safe command invocation and "undo" system.

举个例子:当为一个应用程序编写一个通用的命令调度系统时,很多不同的操作需要作为命令来发布。我们可以使用一个简单的“构建器函数”作为客户端代码的前端。在幕后,这个构建器函数将实际函数签名作为模板参数,派生(通过模板元编程)实际参数和返回类型值,并可能选择合适的特化来存储“备忘录”和“撤消函子”。这些函子既可以在内部存储为函数指针,也可以使用 boost 或 tr1 或 C++11 函数对象存储。通过这种方式,可以构建类型安全的命令调用和“撤消”系统。

回答by Ates Goral

I've used them in a plug-in system where plug-in DLLs could be loaded/unloaded at run-time. I would look for known symbols in each DLL and cast them to function pointers.

我在插件系统中使用过它们,在该系统中可以在运行时加载/卸载插件 DLL。我会在每个 DLL 中查找已知符号并将它们转换为函数指针。