简体   繁体   中英

What is the difference between different ways of passing a function as an argument to another function?

I have the situation where one function calls one of several possible functions. This seems like a good place to pass a function as a parameter. In this Quoara answer by Zubkov there are three ways to do this.

int g(int x(int)) { return x(1); }
int g(int (*x)(int)) { return x(1); }
int g(int (&x)(int)) { return x(1); }
...
int f(int n) { return n*2; }
g(f); // all three g's above work the same

When should which method be used? What are there differences? I prefer the simplest approach so why shouldn't the first way always be used?

For my situation, the function is only called once and I'd like to keep it simple. I have it working with pass by pointer and I just call it with g(myFunc) where myFunc is the function that gets called last.

Expanding on LF's comment, it's often better to eschew function pointers entirely, and work in terms of invocable objects (things which define operator() ). All of the following allow you to do that:

#include <type_traits>

// (1) unrestricted template parameter, like <algorithm> uses
template<typename Func>
int g(Func x) { return x(1); }

// (2) restricted template parameter to produce possibly better errors
template<
    typename Func,
    typename=std::enable_if_t<std::is_invocable_r_v<int, Func, int>>
>
int g(Func x) { return std::invoke(x, 1); }

// (3) template-less, trading a reduction in code size for runtime overhead and heap use
int g(std::function<int(int)> x) { return x(1); }

Importantly, all of these can be used on lambda functions with captures, unlike any of your options:

int y = 2;
int ret = g([y](int v) {
    return y + v;
});

As has been pointed out in the Quora question that you linked to, the first two options use function pointers and the last option uses a function reference.

See this Stack Overflow question for a general discussion on whether it is better to pass a parameter by pointer or by reference.

Generally, references are easier and safer, but pointers are more powerful, as pointers can be reassigned and you can also do pointer arithmetic. This also applies to pointers and references to functions.

Since you expressed that you wanted to keep it simple, I would recommend using references, ie the option on the third line. That way, the compiler will prevent you from doing potentially dangerous things with the reference. I see no advantages to using pointers in your case, since you have no reason to reassign the pointer or do pointer arithmetic.

However, it is also a matter of personal preference whether you use pointers or references. Since I am more of a C programmer than a C++ programmer, I personally prefer pointers to references.

Whether you use references or pointers, the compiler will generate the same machine code (which uses pointers). References are just an abstraction of pointers that only exists in your source code. They will later be converted to pointers when the compiler creates the executable file.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM