• c++ 函数指针


    *****************************
    在有些编程语言中,函数是“第一级值”。在这些语言中,可以将函数作为函数参数
    传递,并把它们当作表达式的组件使用等。
    c++不属于这类语言,但这一点并不是显而易见的。因为对于c++程序而言,将函数作为
    参数传递,并把它们的地址存储在数据结构中是很常见的操作。
    例如,假设我们想对某个数组的所有元素都运用某个给定函数。如果这个函数有一个int
    参数,并且生成void类型,我们可以如下编写代码
    *****************************
    void apply(void f(int), int *p, int n) {
    for (int i = 0;i < n;i++) {
    f(p[i]);
    }
    }
    *****************************
    这是不是说明c++把函数也当作第一级值呢?
    本例中第一个隐蔽之处就是,f虽然看上去像函数,其实根本就不是函数。相反它是一个
    函数指针。和在c中一样c++不可能有函数类型的变量,所以任何声明这种变量的企图都将
    立即被转换成指向函数的指针声明。和在c中一样,所有对函数指针的调用都等价于这个
    指针所指向的函数的调用。所以前面的例子就等价于
    *****************************
    void apply(void (*fp)(int), int *p, int n) {
    for (int i = 0;i < n;i++) {
    (*fp)(p[i]);
    }
    }
    *****************************
    那又怎么样?函数和函数指针之间的有什么重大差异吗?这个差异和任何和任何指针与
    其所指向的对象之间的差异是类似的:不可能通过操纵指针创建这样的对象。c++函数的总
    存储空间在程序执行之前就固定了。一旦程序开始运行,就无法创建新函数了。为了理解
    为什么说不能动态创建新函数是个问题,我们来思考一下如何写一个c++函数,以便把两个
    函数组合起来生成第三个函数。组合是我们所能想到的创建新函数最简单的方法之一。现在
    为了简单期间,我们将假设每个函数都有一个整数参数并返回一个整数结果。然后,假设我
    们有一对函数f和g:
    extern int f(int);
    extern int g(int);
    我们希望能够使用下面的语句:
    int (*h)(int) = compose(f,g);
    具有一种特征,就是对于任何整数n而言,h(n)将等价于f(g(n))。
    c++没有提供直接做这件事的方法。我们可以杜撰如下的代码:
    int (*compose(int f(int), int g(int) ) )(int x) {
    int result(int n) { return f(g(n));}
    return result;
    }
    这里,compose试图用两个函数f和g来定义一个函数,当应用于x时可以得到f(g(x))的函数;
    但是由于两个原因它不可能成功。第一个原因就是c++不支持嵌套函数,这意味着result的定义
    非法。而且由于result需要在块作用域之内访问f和g,所以没有简便的方法可以绕过这个限制。
    简单的使result全局化:
    int result(int n) {return f(g(n));}
    int (*compose(int f(int), int g(int))) (int x)

    return result;

    这个例子的问题在于f和g在result中没有定义。
    第二个问题更难以捉摸。假设c++允许嵌套函数——毕竟c++实现把它当成一种扩展,那么这样
    做会成功吗?
    可惜的是,答案是“实际不会成功”。为了了解原因,我们稍微修改了一下compose函数:
    *****************************

    int (*compose (int f(int), int g(int)))(int x) {
    int (*fp)(int) = f;
    int (*gp)(int) = g;
    int result (int n) {return fp(gp(n));}
    return result;
    }
    *****************************
    其中所做的改变是将f和g的地址复制到两个局部变量fp和gp中去。现在,假设我们调用compose,
    它将返回一个指向result的指针。因为fp和gp是compose的局部变量,所以一旦compose返回它们
    就消失了。如果我们现在调用result,它将试图使用这些局部变量,但是这些变量已经被删除了。
    结果很可能导致程序运行崩溃
    显然编写compose的最后一个版本,我们应该很容易明白这个程序失败的原因。然而,第一个版本
    也存在相同的问题。唯一的不同的是第一个版本中的f和g不是普通的局部变量,而是形参。这个
    区别无关大局:当compose返回时它们也消失;也就是说当result试图访问它们时也会导致崩溃。
    那么显然编写compose函数除了需要常规的基于堆栈的实现外,还需要某种自动回收机制。尽管
    c++将垃圾回收集作为语言的标准部分会给很多方面带来好处,但是存在太多的困难使我们不能这
    样定义c++。


    write by fgd

  • 相关阅读:
    《Windows驱动开发技术详解》之派遣函数
    错误:无法解析外部符号
    《Windows驱动开发技术详解》之Windows内核函数
    《Windows驱动开发技术详解》之Windows内存管理
    《Windows驱动开发技术详解》之驱动程序的基本结构
    《Windows驱动开发技术详解》之编程加载NT式驱动
    二叉搜索树
    Trie树
    判断给定二叉树是否是平衡二叉树
    数字在排序数组中出现的次数
  • 原文地址:https://www.cnblogs.com/wendao/p/cpp_function_learning.html
Copyright © 2020-2023  润新知