简体   繁体   English

c ++作为没有指针的参数

[英]c++ functions as parameters without pointers

When searching for how to pass functions as parameters in C++, I only find examples that use function pointers. 在搜索如何在C ++中将函数作为参数传递时,我只找到使用函数指针的示例。 However the following compiles and outputs "g20" as expected in Visual Studio. 但是,以下内容在Visual Studio中按预期编译并输出“g20”。 Is it better to declare f like this: 这样声明f更好吗:

f(void (*fun)());

instead of 代替

f(void fun());

my example: 我的例子:

#include <iostream>

using namespace std;

int f(void fun());
void g();

int main() {
    cout << f(g);
}

void g() {
    cout << "g";
}

int f(void fun()) {
    fun();
    return 20;
}

You might prefer std::function<> instead of function pointers. 您可能更喜欢std::function<>而不是函数指针。 It can not only store function pointers, but also lambdas, bind expressions, function objects (objects with operator() ), etc. Especially the lambdas will make your API a lot better usable. 它不仅可以存储函数指针,还可以存储lambdas,绑定表达式,函数对象(带有operator()对象)等。特别是lambdas将使您的API更好用。

int f(std::function<void()>& fun) {
    fun();
    return 20;
}

Another way which is simple and does not have the cost of a std:::function is to use templates. 另一种简单且没有std:::function成本的std:::function是使用模板。

template <typename Function>
int f(Function function) {
  function();
  return 20;
}

That way the type will be deduced to be any kind of callable object. 这样,类型将被推断为任何类型的可调用对象。 It should also enable the compiler to inline the call if it can (which is not possible with std::function ). 它还应该使编译器能够内联调用(如果可以的话)(使用std::function是不可能的)。

Both forms are equivalent. 两种形式都是等同的。 I prefer the form which explicitly shows that the parameter is a pointer. 我更喜欢明确显示参数是指针的表单。 The knowledge, that the parameter is a pointer is important, since you can pass the values NULL , nullptr or 0 as argument. 参数是指针的知识很重要,因为您可以将值NULLnullptr0作为参数传递。 Your program would compile, but crash if someone would do the function call f(0) . 您的程序将编译,但如果有人将执行函数调用f(0)则会崩溃。 You always want to check if a function pointer is not a null pointer before calling the pointee, unless you are certain that it is not possible that your function is called with a NULL , nullptr or 0 argument. 在调用指针对象之前,您总是希望检查函数指针是否不是空指针,除非您确定使用NULLnullptr0参数调用函数是不可能的。

If you use lambdas in your project, you should use `templates. 如果在项目中使用lambdas,则应使用`templates。 Otherwise you can continue to use raw function pointers, but make sure that you check your function pointer (if necessary) 否则你可以继续使用原始函数指针,但要确保检查函数指针(如果需要)

template <typename Function>
int f(const Function& functionp) {
  if(functionp)
     functionp();
  return 20;
}

Lambdas and std::function<> objects also have a bool operator, so the line if(functionp) will also work for those. Lambdas和std::function<>对象也有一个bool运算符,所以行if(functionp)也适用于那些。 It will evaluate to false for std::function<> objects which contain a nullptr and otherwise it will evaluate to true for std::function<> objects and lambdas. 它将对包含nullptr的std::function<>对象求值为false ,否则对std::function<>对象和lambdas求值为true

Ampersand & makes it a reference, std::decay_t makes reference a pointer. Ampersand &使其成为引用, std :: decay_t使引用成为指针。

template <class R, class Args...>
using func_ref_t = R(&)(Args...)

template <class R, class Args...>
using func_ptr_t = R(&)(Args...)

According to the C (and C++) standard, when a parameter has a function type, the compiler automatically adjusts it to the corresponding function pointer type. 根据C(和C ++)标准,当参数具有函数类型时,编译器会自动将其调整为相应的函数指针类型。 Therefore, the two are identical as far as the compiler is concerned. 因此,就编译器而言,两者是相同的。

C99 standard section 6.7.5.3 paragraph 8: C99标准第6.7.5.3节第8段:

A declaration of a parameter as ''function returning type'' shall be adjusted to ''pointer to function returning type'', as in 6.3.2.1. 参数声明为''函数返回类型''应调整为''函数返回类型的指针'',如6.3.2.1所述。

C++03 standard section 8.3.5 paragraph 3: C ++ 03标准第8.3.5节第3段:

[...] After determining the type of each parameter, any parameter of type [...] “function returning T” is adjusted to be [...] “pointer to function returning T,” respectively. [...]确定每个参数的类型后,任何类型[...]“函数返回T”的参数分别被调整为“指向函数返回T的指针”。 [...] [...]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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