函数指针的优点

The advantages of function pointer

本文关键字:指针 函数      更新时间:2023-10-16

有人能给我解释一下函数poiner的优点吗?

我知道我的问题有很多可能的重复,但它们只是用文字解释,这不是很有帮助,我需要一个不使用函数指针与使用函数指针的情况相比的例子。

非常感谢。

如何将数据映射到行为,比如:

void DoIt();
void DontDoIt();
std::map<std::string, std::function<void()> word_map {
     {"DoIt", DoIt}, 
     {"DontDoIt", DontDoIt}
};
std::string word;
// ... get "DoIt" or "DontDoIt" into word
word_map[word](); // execute correct function

简单的例子:假设您有一个由姓名和电话号码组成的N记录。

您被要求对进行排序

  • 基于名称
  • 基于电话号码

一个很好的方法就是在排序例程中改变作为函数指针传递的比较函数。

void sort( records r[], int N, 
           bool (*fptr)( const record& lhs, const record& rhs ) ) { }

若你们不使用函数指针,那个么你们将只为两个不同的比较函数编码相同的逻辑。

void sort_by_name( records r[], int N) {  }
void sort_by_phoneno( records r[], int N) {  }

例如,通过使用函数指针,可以防止代码重复。

没有函数指针:

void AddOneToVectorElements( vector<int> v )
{
    // implementation
}
void MultiplyVectorElementsByTwo( vector<int> v )
{
    // implementation
}
// usage
AddOneToVectorElements(v);
MultiplyVectorElementsByTwo(v);

使用函数指针:

typedef int (*func)(int);
int TransformVecotr ( vector<int> v, func f)
{
    // implementation by application of f to every element
}
int AddOne(int x)
{
    return x + 1;
}
int MultiplyByTwo(int x)
{
    return 2 * x;
}
// usage
TransformVecotr(v, &AddOne);
TransformVecotr(v, &MultiplyByTwo);

在C++11中有lambda函数,它们使整个过程更加方便。

关键是函数指针在泛型编程中一直被"隐藏"使用。人们往往会忘记这一点,因为模板参数推导隐藏了函数指针语法

例如:

#include <algorithm>
#include <iterator>
bool f(int i)
{
    return i == 1;
}
int main()
{
    int arr[] = { 1, 1, 3 };
    int count = std::count_if(std::begin(arr), std::end(arr), f);
}

main的最后一行中的f是一个函数指针,因为std::count_if模板函数将接受任何可以与()语法一起使用的内容。引用cppreference.com:

template< class InputIt, class UnaryPredicate >
typename iterator_traits<InputIt>::difference_type
    count_if( InputIt first, InputIt last, UnaryPredicate p );

UnaryPredicate可以是函数指针,并且是上面示例中的一个。

编译器只是在传递f时自动推导出它的确切类型bool(*)(int)。从技术上讲,你也可以这样写电话:

// just for illustration:
std::count_if<int*, bool(*)(int)>(std::begin(arr), std::end(arr), f);

如果C++中没有函数指针,那么在标准库算法中就不能直接使用函数作为谓词。相反,你必须一直把它们封装在类中:

#include <algorithm>
#include <iterator>
bool f(int i)
{
    return i == 1;
}
struct Functor
{
    bool operator()(int i) const
    {
        return f(i);    
    }
};
int main()
{
    int arr[] = { 1, 1, 3 };
    int count = std::count_if(std::begin(arr), std::end(arr), Functor());
}