【专业知识】C/C++指针三

今天我们主要介绍函数指针、函数的指针参数以及返回指针的函数

A) 函数指针   C++规定,一个函数的地址就是这个函数的名字。我们需要指出的就是一个指针需要指定类型是为了后来的指针解析时候使用,通过指针有效快速访问对象。那么对于函数的指针,它要表示出该函数的那些特性才能满足解析的唯一性呢?答案就是一个函数的特性有它的参数列表和返回类型。 下面是一个函数指针的例子:

int (*p)(int i,int j);

不能是

int *p(int i,int j),

这样就变成了返回指针的函数声明了。

在C++中处于对安全性的考虑,指针和它指向的对象要类型一致,也就说上面的指针所指向的函数的特性要和它一模一样:例如指向int min(int I,int j);是可以的。但是指向int min(double I ,double j);是不可以。函数指针也和其他的指针一样,在使用的时候很怕发生"悬空",所以在使用的时候同样要判断有效性,或者在定义的时候就初始化。

int (*p)(int i,int j)=min;

int (*p)(int i,int j)=&min;

int (*p)(int i,int j)=0;

B) 函数的指针参数 函数指针可以作函数的参数:例如我们有一个积分的算法,对于不同的数学函数可以进行积分(我们这里假设函数都是一元的). 那么我们的算法接口可以定义为:

templateT

integrate( T lower, T upper , T (*)(T)=0 )throw(integrated_exp);

这里的最后的参数是一个函数的指针,并且被设定缺省值为0。这个函数返回一个值,同时需要一个参数。假如加入我们有这样的一个函数:

double line(double x)

{

return a*x+b;

}

那么我就可以使用了。 函数指针还可以作为返回类型(注意不是函数!!,某个特定的函数是不可以作为返回类型的。)假设:

typedef int (*PF)(int );

PF getProcessMethod( );//true

C) 返回指针的函数 一个函数的返回是函数的重要接口之一,c++的一个重要的强大的功能就是能够设计足够复杂和好用的用户自定义类型。而同时处理和传递这些类型也是很麻烦的一件事情,我们不想把我们的时间都花在这些对于我们的实际工作没有很实质帮助的拷贝上,解决这个问题就要依赖我们的接口设计:c和c++都提供了相应的解决方案,在c++中我们可是使用引用,讲他们作为函数的实际参数,或者我们在函数的实际参数中使用一个指针等。同样我们还可以使用一个函数返回一个指针:但是这是一个很不好解决的问题! 我们首先容易出错的是:将一个局部变量的地址传出来!例如:

UserType * Process( )

{

UserType ut(param-list);

//process ut;

return &ut;

}

这个变量在我们的函数结束的时候就被销毁了,尽管地址可以传出去,但是这个地址已经不存在了,已经不能使用的东西,在这个函数之外却不知道,难免要出错! 同时我还会有一个比较麻烦的问题:使用new,又容易造成内存泄露

UserType * Process()

{

UserTpye *put=new UserType(param-list );

//process put;

return put;

}

我们在函数内部使用了一个new,分配了一个空间,这样传出来也是可以!就是说不会发生上面的问题了。但是用户通常都会忘记在程序的外面在把这个借来的空间还回去!内存空间就这样泄露了! 可能也是这些另人无奈的问题,所以很多程序员把函数的参数设定为指针或者引用,以此来代替这种向外传输吧!总之,使用这种返回指针的函数要小心!

原文发布于微信公众号 - 程序员互动联盟(coder_online)

原文发表时间:2015-05-27

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏老马说编程

计算机程序的思维逻辑 (12) - 函数调用的基本原理

栈 上节我们介绍了函数的基本概念,在最后我们提到了一个系统异常java.lang.StackOverflowError,栈溢出错误,要理解这个错误,我们需要理...

18810
来自专栏塔奇克马敲代码

第 17 章 标准库特殊设施

1413
来自专栏从零开始学 Web 前端

从零开始学 Web 之 ES6(五)ES6基础语法三

在这里我会从 Web 前端零基础开始,一步步学习 Web 相关的知识点,期间也会分享一些好玩的项目。现在就让我们一起进入 Web 前端学习的冒险之旅吧!

642
来自专栏北京马哥教育

提升Python程序性能的7个习惯

使用局部变量替换模块名字空间中的变量,例如 ls = os.linesep。一方面可以提高程序性能,局部变量查找速度更快;另一方面可用简短标识符替代冗长的模块变...

510
来自专栏desperate633

深入理解Java中的内存泄漏内存泄漏内存泄漏发生的原因造成内存泄露的常见情形内存泄露的解决方案

Java的一个最显著的优势是内存管理。你只需要简单的创建对象而不需要负责释放空间,因为Java的垃圾回收器会负责内存的回收。然而,情况并不是这样简单,内存泄露还...

751
来自专栏noteless

[十七]JavaIO之CharArrayReader 和 CharArrayWriter

他们的逻辑类似ByteArrayInputStream ByteArrayOutputStream,只不过一个是字节,一个是字符而已

833
来自专栏WD学习记录

基本一

1.extern可以置于变量或者函数前,以表示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。另外,extern也可用来进行...

1285
来自专栏JetpropelledSnake

Python入门之@classmethod与@staticmethod

本章内容:     1. @classmethond     2. @staticmethod ================================...

3686
来自专栏Python小屋

Python使用marshal模块操作二进制文件

Python标准库marshal可以进行对象的序列化和反序列化。 >>> import marshal # 待序列化的对象 >>> x1 = 30 >>> x2...

2715
来自专栏专注 Java 基础分享

Java 的字节流文件读取(一)

1717

扫码关注云+社区