1 函数指针的形式是int (*pf)(int, char); pf指向返回值为int型,参数为int & char类型的函数。如果写作int * pf(...)则是返回值为指向int的指针,而不是
假如PrintMin是相应的函数,则pf=PrintMin;将函数的地址赋值给pf,函数名即代表函数地址。pf(x,y);即可调用函数
如果
int Mycompare(const void *a, const void *b);
int (*q)(const void*,const void *);其中任何类型的指针都可以转换为void *,并且在转换回原来的类型时不丢失信息
q=Mysquare;
int *q1 = &a, *q2 = &b;
printf("\n%5d", (*q)((void *)q1, (void *)q2));
qsort(num, MAX, sizeof(int), q);
这几个语句可以说明函数指针,其中第二句是定义指针。最后一句是一个快排库函数,最后的q可以直接写为Mycompare,因为Mycompare也是函数的地址。在qsort函数中的形参q就是一个函数地址,而不是常见的函数值q(),因为调用qsort时原型是void qsort(void *v[],int left, int right, int(*comp) (void*,void*)),q的地址直接赋值给comp,comp是一个指针,指向返回值为int,参数为两个void *的函数。
2 指针数组。
char *lineptr[Maxlines];中,[]的运算级别比 *高,所以lineptr是一个数组,数组里的元素是char *类型的指针。
char (*lineptr)[Maxlines];中,定义一个lineptr指针,指向一个char类型的数组。
所以,argv *[]中,得到的参数是数组,数组里面的元素都是char *类型的指针,指向命令行参数。所以如果在命令行中敲入echo hello, world时,argc值为3,argv[0],argv[1],argv[2]分别是“echo ”“hello,”“world”而不必长度相同
3 引用int &r=n;这时候r和n就是同一个变量(两个变量地址相同),改变n或者r都对两个变量有效。a 定义引用时候进行初始化 b只能引用一个变量,不能改变变量,也不能引用常量和表达式 。
引用的作用可以体现在swap()函数中。
通常
swap(&x,&y);
void swap(int *a,int *b)
{
int tmp;
tmp=*a;*a=*b;*b=tmp;
}
有了引用后可以
swap(x,y);
void swap(&a,&b)
{
int tmp;
tmp=a;a=b;b=tmp;
}
这里,ab分别引用了xy,不需要利用地址可以直接进行值的交换。
有一个比较炫的功能叫做函数引用,如下
int n;
int &SetValue(){return n;}
int main(void)
{
SetValue()=40;
cout<<n;
}
引用的是全局变量n,输出结果为40.
4 在C++中,用const常量比#define多,便于类型检查。
const int *p;定义一个常量指针,不可以通过p修改所指向变量的值,但是可以修改p指向的变量是谁。
即可以p=m;p=n;不能*p=4;
不可以把常量赋值给非常量,但是可以把一个非常量赋值给常量。
例如const int *p1; int *p2;
p1=p2;//可以
p2=p1;//不行,这样如果修改p2,有可能涉及到修改p1
但是可以强制类型转换p2=(int *p1);
5 使用new进行动态内存分配
P=new T;//其中T是一种变量的类型名,P是T *类型的指针。动态内存分配为P分配一块大小为sizeof(T)字节的空间给P。如
int *pn;
pn= new int;
*pn=5;
相当于C语言里面的malloc();,如free()函数一样,C++中有delete函数,delete P; 将P指向的内存空间释放。但是对一个指针,只能进行一次释放,也即只能用一次delete P;
也可以分配一个数组,例如
P=new T[N];这样P指向大小为sizeof(T)*N的内存空间的起始地址。N可以是表达式。对于动态分配数组型的内存空间时,
delete []P;进行空间释放。如果没有[],就会只释放P指向的sizeof(T)大小的空间,还是会有内存的损耗。
6 内联函数、函数重载
函数调用有时间开销,调用函数时先把参数和返回地址放到栈里,执行函数,然后再从栈中取出返回地址和参数继续执行。通常情况下这种时间消耗忽略不计,但是如果调用函数次数多,函数本身语句少执行快,调用所产生的开销就占比就比较大。这时候使用内联函数:编译器将整个函数的代码插入到调用语句处,不会产生调用函数的语句。
在函数体的函数名前加上inline指令,例如inline int Max(int a,int b){...}就可以了。inline指令的添加是在函数定义的地方进行操作的,例如类的内联成员函数写法如下:
class B
{
inlinevoid func1();
};
class B::func1(){}
内联函数的定义必须对编译器可见,便于编译器在调用点内联展开该函数的代码。把内联函数的定义放在头文件中,可以确保在调用函数时所使用的定义是相同的,并保证在调用点对该函数的定义对编译器可见。
一个或多个函数,名字相同,参数个数和类型不同,叫做函数重载。
int Max(double, double);
int Max(int,int);
int Max(int,int,int);
编译器根据调用语句的实参的个数和类型判断应该调用哪个函数,使得函数命名变得简单。但是上述三个Max定义不知道怎么处理Max(3,2.4);,编译器报错。函数重载允许返回值的类型不同。
如果函数名相同,参数相同,返回值不同,属于函数的重复定义。
7 函数缺省
在C++的函数中,允许函数缺省,就是在函数头处给出缺省值,在最右的连续若干个参数有缺省值,注意,是最右和连续。
如果void func(int x1,int x2=2, int x3=3){}
则在函数调用时候,func(10);<=>func(10,2,3);
C++的很多机制用来提高程序的可扩充性,函数缺省的目的在于后期维护。如果某个写好的函数要添加新的参数,原先那些调用该函数的语句可能很多,分散很广,也不一定需要使用新参数,为了避免修改原先的函数调用语句,可以使用缺省参数。