c++学习笔记(3.函数的升级)(一)

2014-11-24 02:32:53 · 作者: · 浏览: 5
本节知识点:
1.内联函数:
a.内联函数的来源:c++中使用const常量代替#define宏常量,如 const int a = 10; 与 #define a 10,这样就可以避免宏的副作用。那c++用什么替代宏代码片段呢?就是使用内联函数。
b.内联函数其实是对c++编译器的一种内联请求,内联函数在最终生成的代码中是没有定义的,c++编译器直接将函数体插入到函数调用的地方,并且没有普通函数调用时的额外开销(压栈、跳转、返回),所以说它可以代替宏代码片段。同时内联函数是一种特殊的函数,它依然具有函数的特性(参数检查、返回类型),使用起来比宏代码片段要安全的多(内联函数是由编译器处理的,直接将编译后的函数体插入调用的地方,而宏代码片段是由预编译器处理的,进行简单文本替换,没有任何编译过程)。因为内联函数是对编译器的请求,所以编译器不一定会允许内联请求!(这个跟编译器的设置选项中的优化级别有关系)
c.内联函数的形式:有两种,第一种就是在普通函数的定义和声明两处都加上inline关键字,把函数标记为内联请求。代码如下:
[cpp]
inline int fun(void);
inline int fun(void)
{
printf("hello!\n");
return 1;
}
第二种,使用g++提供的扩展语法__attribute__((always_inline)),对函数进行强制内联,代码如下:
[cpp]
inline int fun(void) __attribute__((always_inline));
inline int fun(void)
{
printf("hello!\n");
return 1;
}
d.c++中的内联编译的限制:
第一:不能存在任何形式的循环语句
第二:不能存在过多的条件判断语句
第三:函数体不能过于庞大
第四:不能对函数进行取址操作
第五:函数内联声明必须在调用语句之前
注意:编译器对于内联函数的限制并不是绝对的,内联函数相对于普通函数的优势只是省去了函数调用时压栈,跳转和返回的开销。因此,当函数体的执行开销远大于压栈,跳转和返回的开销时,那么内联就毫无意义了。
e.内联函数的实现机制:
当请求内联的函数,满足内联要求的时候,c++编译器就将内联函数存入符号表中,当调用这个函数的时候,就用符号表中的函数体进行替换。
2.函数默认参数:
a.函数默认参数的定义:c++中可以在函数声明时为参数提供一个默认值,当函数调用时没有指定这个参数的值,编译器会自动用默认值替代。代码如下:
[cpp
#include
int fun(int i = 10);
int main()
{
printf("%d\n",fun());
printf("%d\n",fun(2));
return 0;
}
int fun(int i)
{
return i+i;
}
b.函数默认参数的规定:只有参数列表后面部分的参数才可以提供默认参数值,一旦在一个函数调用中开始使用默认参数值,那么这个参数后的所有参数都必须使用默认参数值
正确代码:
[cpp]
int add(int a,int b = 0,int c = 0);
错误代码:
[cpp]
int add(int a = 0,int b,int c = 0); //因为你在调用这个add函数的时候,总不能这样吧add(1,,2);
3.函数占位参数:
a.在c++的规范中,允许使用函数占位参数,函数的占位参数在函数的声明和定义中,只有类型而没有名字,只为接受一个无用的参数而已。就像是scanf中%*d一样,起一个占位的作用。代码如下:
[cpp]
#include
int fun(int a,int b,int);
int main()
{
fun(1,2,3);
return 0;
}
int fun(int a,int b,int)
{
return a+b;
}
b.函数占位参数有两个用途:
第一个用途是,函数占位参数与函数默认值结合到一起使用,为以后的程序扩展留下伏笔,代码如下:
[cpp]
#include
int fun(int a,int b,int = 0); //一般int = 0 就是为以后函数改进做准备 是一种习惯
int main()
{
fun(1,2,3);
return 0;
}
int fun(int a,int b,int)
{
return a+b;
}
第二种用途是,兼容 c语言中书写不规范的代码,因为c语言函数有一个缺陷,就是void fun()没有函数参数的函数,可以接受任意个数,任意类型的函数参数。如果要把一个定义为void fun()的函数,调用的时候写成了fun(1,2); 在工程代码中,想要移植到c++环境中,去改fun(1,2)为fun(),可能工作量会很大,所以可以直接把函数定义改成void fun(int,int),工程也可以使用了!
4.函数的重载:
a.重载的定义:用同一个函数名定义不同的函数,即当函数名和不同的参数搭配时函数的含义不同。代码如下:
[cpp]
#include
int fun(int a)
{
printf("aaa %d \n",a);
}
int fun(int i,int j)
{
printf("iii %d jjj %d\n",i,j);
}
int fun(char* s)
{
printf("%s\n",s);
}
int main()
{
fun(10);
fun(1,2);
fun("hello");
return 0;
}
b.重载的条件(至少满足下面三个条件之一):
第一:参数个数不同 int fun(int a) 与 int fun(int a, int b)
第二:参数类型不同 int fun(int a) 与 int fun(char a)
第三:参数顺序不同 int fun(int a, char b) 与 int fun(char b, int a)
注意:函数的返回值类型,不是重载的条件。int fun(int a) 与 char fun(int a) 这个两个函数是不能重载的
c.注意在使用函数重载的时候,不要使用函数默认参数。二者不要同时使用,会出现二义性,编译器会报错!!!代码如下:
[cpp]
#include
int fun(int a)
{
printf("aaa %d \n",a);