C++指针解读(7)-- 指针和函数

前面我们讲过用指针变量作为函数参数。这里讲指向函数的指针变量和返回指针的函数。

1、指向函数的指针变量

跟变量一样,函数也会存储在内存空间中,函数的内存空间有一个起始地址,每次调用函数时就从该入口地址开始执行函数代码。

既然函数有地址,我们就可以定义一个指向该函数的指针变量。比如,我们可以定义这样的指针变量:

int (*pfun)();

从右往左读,先是(),表示这是一个函数;然后是(*pfun),表示一个指针指向这个函数;最后是void,表示这个函数返回int。

如果我们把指针的挂号去掉:

int *pfun();

则表示一个返回int*类型的函数。

所以,定义指向函数的指针变量的形式为:

(1)类型名 (*指针变量名)(函数参数列表)

(2)typedef 类型名 (*指针变量名)(函数参数列表)

这里必须注意,一个函数的指针变量只能指向定义时指定的类型的函数。比如int (*p)()表示函数指针变量p可以指向返回值是int的无参数函数。

2、函数指针的使用

我们来看一个使用函数指针的例子:

int max(int a, int b) {
    if (a > b) {
        return a;
    }
    else {
        return b;
    }
}

int main()
{
    int a = 3;
    int b = 7;

    int (*p)(int, int);
    p = max;
    int ret = p(3, 7);
    //也可以这么调用
    //int ret = (*p)(3, 7);
    printf(" max = %d\n", ret);

    return 0;
}

使用函数指针的注意事项:

(1)函数指针只能指向定义时指定的函数类型。比如int (*p)(int, int)就只能指向返回值是int,形参列表是2个int的函数。比如int max(int a, int b); int min(int a, int b)等这样的函数都可以。

(2)函数指针变量要调用哪个函数,就让指针指向哪个函数。

比如p = max,这里形参的列表是不用写的,只要写函数名就可以了。因为函数名代表函数的入口地址,让函数指针指向这个入口地址就可以了。

(3)用函数指针变量代替函数运行,比如p(a, b)。

(4)函数指针变量不能进行算术运算,p+n, p++等都是错误的。

3、用函数的指针作函数参数

指向函数的指针可以作为函数参数,把函数的指针作为形参,这样就能够在被调用函数中使用实参函数。

有下面几种传递函数指针的方式:

(1)显式地将形参定义为指向函数的指针

void func(int nValue,int (*pf)(int,int));

(2)第二个形参为函数类型,会自动转换为指向此类函数的指针

void func(int nValue,int pf(int,int));

(3)

typedef int (*PF)(int, int);

void func(int nValue, PF pf)

例子:

int add(int i, int j) {
    return i + j;
}

int sub(int i, int j) {
    return i - j;
}

typedef int (*pfun)(int i, int j);
int compute(pfun fun, int i, int j) {
    return fun(i, j);
}

int main()
{
    int a = 3;
    int b = 7;
    int (*pf1)(int i, int j);
    pf1 = sub;

    std::cout << compute(pf1, b, a) << std::endl;

    return 0;
}

4、函数指针数组

函数指针也可以存放在数组中。

假如有这么一个应用场景,系统需要根据输入的参数来选择需要执行的具体函数。

输入'+',则执行add()函数;输入'-',则执行sub()函数。

typedef int (*operation)(int i, int j);
operation ops[128] = { 0 };
ops['+'] = add;
ops['-'] = sub;

operation op1 = ops['+'];
printf(" 3 + 4 = %d\n", op1(3, 4));

operation op2 = ops['-'];
printf(" 7 - 3 = %d\n", op2(7, 3));

这里我们用'+', '-'作为数组的索引,因为char其实就是int类型,我们把数组长度定义为128,是因为ASCII共有128个字符,这样每个ASCII字符都能作为数组的索引存放。

5、返回指针值的函数

定义返回指针值的函数的形式为:

类型名 *函数名(参数列表)

返回指针时要注意这几种情况:

(1)如果返回的是函数内部局部变量的指针,那么这个指针出函数作用域时,其指向的对象已经失效。这种情况下就成了迷途指针或悬空指针。

int* invalidPointer() {
    int tmp = 3;

    return &tmp; //出函数后tmp对象已被释放,返回的指针成了: 迷途指针/悬空指针
}

(2)如果是在函数内部动态分配了内存的指针,记得在函数外部释放内存,避免产生内存泄漏。

int* localPointer() {
    int* pi = (int*)malloc(sizeof(int));
    return pi;
}
相关推荐
做人不要太理性11 分钟前
【C++】深入哈希表核心:从改造到封装,解锁 unordered_set 与 unordered_map 的终极奥义!
c++·哈希算法·散列表·unordered_map·unordered_set
程序员-King.20 分钟前
2、桥接模式
c++·桥接模式
chnming198724 分钟前
STL关联式容器之map
开发语言·c++
程序伍六七37 分钟前
day16
开发语言·c++
小陈phd1 小时前
Vscode LinuxC++环境配置
linux·c++·vscode
火山口车神丶1 小时前
某车企ASW面试笔试题
c++·matlab
是阿建吖!2 小时前
【优选算法】二分查找
c++·算法
Ajiang28247353044 小时前
对于C++中stack和queue的认识以及priority_queue的模拟实现
开发语言·c++
‘’林花谢了春红‘’8 小时前
C++ list (链表)容器
c++·链表·list
机器视觉知识推荐、就业指导10 小时前
C++设计模式:建造者模式(Builder) 房屋建造案例
c++