C++学习第8篇-函数深入
2012-02-29 11:39
232 查看
1. 函数的形参和实参
1)形参和实参
通常的使用,函数参数(形参)和函数自变量(实参)是互通的。
函数形参-在函数原型和函数声明中的变量:
函数实参-函数调用时,传入代替函数形参的变量;
注意:函数的形参只有局部变量的范围,函数调用结束,形参自然销毁;
3种传参方式:传值、传引用和传地址
2. 值传递
值传递-将实参赋值给函数执行;
因为只是传递一个实参的拷贝,函数不能修改原来实参的值;
值传递的优点:
A)可以传递变量、数值和表达式;
B)参数不会被修改;
缺点:传递如结构体、类,需花费很长的时间;
在多数情况下,值传递是最好的函数参数传递方式,灵活和安全。
3. 引用传递
值传递的返回值,只能通过函数的return来实现;
在多数情况下,值传递是合适的;但如需改变参数的值,如重排列一个数组时,修改实参是有效和清晰的;
引用传递,就可以修改参数的值;
再如:
函数一般只有一个返回值,如需返回多个值,只需传递多个引用即可:
2)常量引用传递
引用传递,没有值传递时结构体或者类对象时耗时;引用传递创建真正的实参,不拷贝任何信息;
引用传递中,函数可以修改参数的值;如果不允许修改,可以采用常量引用才传递:
上面例子会出现编译错误的!
使用常量引用传递的几个原因:
A)协助编译器保证不能改变的参数不会修改;B)告诉编程人员留意参数是否会被修改;C)帮助编程人员调试错误值。
记住:通常采用常量引用传递,除非你确实需要改变参数的值。
引用传递的优点:
A)允许函数修改参数的值,有时非常有用的;B)引用不涉及到复制参数的信息,所以较快;
C)可以传递常量引用,防止无目的的修改; D)可以返回多个值。
缺点:
A)非常量引用不能是数值和表达式,只能是变量;B)比较困难清晰说明传递的引用是输入、输出还是两者皆是;
C)不能从函数调用确定参数是否被修改;
引用传递比值传递速度较慢!
4. 地址传递
地址传递是另一种变量传递方式,只传递变量的地址,而不是变量本身;函数形参必须是指针。
地址传递的典型应用在内存动态分配和数组访问:
以上例子中,必须传入数组的长度。
通常,在解引用地址传递的参数之前,最好对其进行空指针判断:
地址传递的优点:
A)允许函数改变参数的值;B)因为不进行拷贝,速度比较快;C)可以返回多个值。
缺点:A)参数不能为数值或表达式,必须是正常的变量;C)所有参数必须检查是否为空指针;D)较值传递慢。
引用传递通常比地址传递安全,引用传递是多数时候使用的方式。
2)值传递、引用传递和地址传递没有很大的区别:
A)引用传递,在编译器处理时,只作为指针处理;
B)和指针和引用传递的主要区别是引用传递有比较清晰和严格的语法;所以引用传递更安全,但相对不够灵活;但在效率上是不相上下的。
D)地址传递只是传递地址的地址值,若函数改变此地址值,只是改变了临时值,没有改变地址的实际值。
尽管地址传递实际上是值传递,但依然可以修改传递地址的存储的值;这时引用传递、地址传递和值传递的区别。
若需通过地址传递来修改参数的实际指向地址,可以传递地址的引用:
结论是:引用是指针,指针的地址是值传递。
5. 返回值是值、引用和地址
值、引用和地址的返回给函数调用几乎是一样的。
1)值返回是最简单和最安全的方式:
返回的变量或表达式可以包含函数声明的局部变量;
对于结构体和类对象是比较慢的;
2)引用返回
引用返回必须是变量,调用者可以继续使用该引用修改变量,很多时候是比较有用的,而且比较快速;
注意不能返回函数的局部定义的变量引用:
3)地址返回
地址返回只能返回变量的地址,不能是数值和表达的;
地址返回也是比较快速的,不能返回局部变量的地址;
若返回的是调用函数的局部定义变量的地址,编译器会产生警告信息的;
地址常用之一就是返回新的分配内存给调用者:
小结:
一般值返回是足够使用的,足够灵活和安全;引用返回和地址返回是比较有用的,特别是针对结构体和类对象的动态分配地址;
注意在引用返回和地址返回时,确保返回的不是函数自定义的局部变量的引用或地址。
6. 内联函数
函数的使用有几大好处:函数代码可重用;比较容易改变和更新代码;使代码更易读和易写;提供了类型检查;
每次的函数调用,往往需要付出更多的操作;就地编码较好;
就地编码即调用函数时,直接将代码嵌入当前位置;这是所谓的内联函数,使用关键字inline
内联函数比较适合短函数,特别是在循环内,而没有分支。
7. 函数重载
函数重载是C++一大特性,允许创建不同的函数使用相同的名称,而使用不同的参数;
注意函数的返回类型不能作为函数重载的标志;使用typedef不能理解为创建一个新的类型;
匹配重载函数可能出现的3中情况:
1) 找到匹配函数;2) 没有找到匹配函数;3) 多个重载函数符合条件(歧义匹配)。
匹配重载函数的过程:
1)寻找最合适的;2)通过合理转换的匹配(参数的升级转换,如char->int);
3)通过强制的标准转换(如int->double);4) 当以上都没有找到,C++会遍历用户自定义函数;
歧义匹配属于编译运行错误。
处理歧义匹配:
1)定义一个新的重载函数;
2)显式转换歧义的参数到确定的类型;
小结:函数调用会明显降低函数的灵活性,同时附带少许的风险;函数重载或许比较复杂,但非常实用。
8. 默认参数
默认参数,即函数的形参已经赋予初始值。
默认参数是非常出色的选择,当函数需要的默认的值,用户可以也不需要修改;
注意:多于多个默认值,不能跳过赋值;
A) 所有的默认参数必须是由右到左的;B) 最右边的默认值是最常覆盖修改的;C) 默认值不能作为函数重载的标志。
9. 函数指针
函数指针是比较高级的话题;对于数组名是一个地址,那么函数名可以理解是函数的地址;
函数调用时,首先解引用函数名(即函数地址),获取函数的地址入口,才开始执行;
函数指针即指针指向函数的地址,函数指针可以重定向:
因为()的优先级比*高,所以函数指针必须加括号:
注意:函数指针的签名(包括参数、返回值等)必须匹配指向的函数的签名。
函数指针调用,就如指向的函数的隐式调用一样,如pFoo() ;
函数指针的通常应用是函数实现特定的功能,但你想用户可以自定功能的实现;
如选择排序:
10. 栈和堆
程序使用的内存区域分4个部分:
A)代码区:编译的程序放置的地方;B)全局区:存放全局变量的地方;C)堆:动态分配的变量存放地方;D)栈:形参和局部变量存放的地方。
1)堆-自由存放区,是动态分配的一个巨大缓冲池;
必须知道:顺序的存储请求,不一定得到实际上的顺序存储区域;
当动态分配的内存释放,返回堆,作为新的可以分配的内存;
2)栈:只能从顶部取出和放入的操作:
top()、pop()、push()是常用的操作;
栈是first in, last out(FILO)的结构;
当栈的的存储区域已经满了,就会出现溢出。
不必要详细了解栈的工作细节。
11. 递归
C++的递归就是函数的自身调用。
递归必须有终止条件,否则就为无限递归。如:
再如:求1到nValue的和:
示例3:Fibonacci数:
12. 命名空间
命名空间概念,确切来说不归入函数这部分,但是十分重要的概念。
程序中出现标识符(变量或函数名)在相同的范围,即命名冲突。
这时,可以使用命名空间来解决,通过全局::运算符,来调用所需函数或变量;
亦可以通过using关键字,引入命名空间。
13. 捕捉错误
错误包括断言、错误、退出和异常。
编程中,你不可能避免错误,包括语法和词义错误;
语法错误-没有按照相应的语言的语法格式编程;
词义错误-程序没有按照编程人员的意愿,实现目标;不能被编译器捕捉,
A)逻辑错误;B)冒犯性假设错误。
处理:
A)防御错误;B)探测错误;
2)断言-Assert
如果断言的条件是true,程序不过处理,如果断言的条件是false,则程序发出错误异常消息并终止程序;
至此,C++面向过程编程已学习完毕,后面部分为C++面向对象编程的学习。Have Fun!!!!!!!
【免责特此声明:
1)本内容可能是来自互联网的,或经过本人整理的,仅仅代表了互联网和个人的意见和看法!
2)本内容仅仅提供参考,任何参考该内容造成任何的后果,均与原创作者和本博客作者无关!】
1)形参和实参
通常的使用,函数参数(形参)和函数自变量(实参)是互通的。
函数形参-在函数原型和函数声明中的变量:
函数实参-函数调用时,传入代替函数形参的变量;
注意:函数的形参只有局部变量的范围,函数调用结束,形参自然销毁;
3种传参方式:传值、传引用和传地址
2. 值传递
值传递-将实参赋值给函数执行;
因为只是传递一个实参的拷贝,函数不能修改原来实参的值;
值传递的优点:
A)可以传递变量、数值和表达式;
B)参数不会被修改;
缺点:传递如结构体、类,需花费很长的时间;
在多数情况下,值传递是最好的函数参数传递方式,灵活和安全。
3. 引用传递
值传递的返回值,只能通过函数的return来实现;
在多数情况下,值传递是合适的;但如需改变参数的值,如重排列一个数组时,修改实参是有效和清晰的;
引用传递,就可以修改参数的值;
再如:
函数一般只有一个返回值,如需返回多个值,只需传递多个引用即可:
2)常量引用传递
引用传递,没有值传递时结构体或者类对象时耗时;引用传递创建真正的实参,不拷贝任何信息;
引用传递中,函数可以修改参数的值;如果不允许修改,可以采用常量引用才传递:
上面例子会出现编译错误的!
使用常量引用传递的几个原因:
A)协助编译器保证不能改变的参数不会修改;B)告诉编程人员留意参数是否会被修改;C)帮助编程人员调试错误值。
记住:通常采用常量引用传递,除非你确实需要改变参数的值。
引用传递的优点:
A)允许函数修改参数的值,有时非常有用的;B)引用不涉及到复制参数的信息,所以较快;
C)可以传递常量引用,防止无目的的修改; D)可以返回多个值。
缺点:
A)非常量引用不能是数值和表达式,只能是变量;B)比较困难清晰说明传递的引用是输入、输出还是两者皆是;
C)不能从函数调用确定参数是否被修改;
引用传递比值传递速度较慢!
4. 地址传递
地址传递是另一种变量传递方式,只传递变量的地址,而不是变量本身;函数形参必须是指针。
地址传递的典型应用在内存动态分配和数组访问:
以上例子中,必须传入数组的长度。
通常,在解引用地址传递的参数之前,最好对其进行空指针判断:
地址传递的优点:
A)允许函数改变参数的值;B)因为不进行拷贝,速度比较快;C)可以返回多个值。
缺点:A)参数不能为数值或表达式,必须是正常的变量;C)所有参数必须检查是否为空指针;D)较值传递慢。
引用传递通常比地址传递安全,引用传递是多数时候使用的方式。
2)值传递、引用传递和地址传递没有很大的区别:
A)引用传递,在编译器处理时,只作为指针处理;
B)和指针和引用传递的主要区别是引用传递有比较清晰和严格的语法;所以引用传递更安全,但相对不够灵活;但在效率上是不相上下的。
D)地址传递只是传递地址的地址值,若函数改变此地址值,只是改变了临时值,没有改变地址的实际值。
尽管地址传递实际上是值传递,但依然可以修改传递地址的存储的值;这时引用传递、地址传递和值传递的区别。
若需通过地址传递来修改参数的实际指向地址,可以传递地址的引用:
结论是:引用是指针,指针的地址是值传递。
5. 返回值是值、引用和地址
值、引用和地址的返回给函数调用几乎是一样的。
1)值返回是最简单和最安全的方式:
返回的变量或表达式可以包含函数声明的局部变量;
对于结构体和类对象是比较慢的;
2)引用返回
引用返回必须是变量,调用者可以继续使用该引用修改变量,很多时候是比较有用的,而且比较快速;
注意不能返回函数的局部定义的变量引用:
3)地址返回
地址返回只能返回变量的地址,不能是数值和表达的;
地址返回也是比较快速的,不能返回局部变量的地址;
若返回的是调用函数的局部定义变量的地址,编译器会产生警告信息的;
地址常用之一就是返回新的分配内存给调用者:
小结:
一般值返回是足够使用的,足够灵活和安全;引用返回和地址返回是比较有用的,特别是针对结构体和类对象的动态分配地址;
注意在引用返回和地址返回时,确保返回的不是函数自定义的局部变量的引用或地址。
6. 内联函数
函数的使用有几大好处:函数代码可重用;比较容易改变和更新代码;使代码更易读和易写;提供了类型检查;
每次的函数调用,往往需要付出更多的操作;就地编码较好;
就地编码即调用函数时,直接将代码嵌入当前位置;这是所谓的内联函数,使用关键字inline
内联函数比较适合短函数,特别是在循环内,而没有分支。
7. 函数重载
函数重载是C++一大特性,允许创建不同的函数使用相同的名称,而使用不同的参数;
注意函数的返回类型不能作为函数重载的标志;使用typedef不能理解为创建一个新的类型;
匹配重载函数可能出现的3中情况:
1) 找到匹配函数;2) 没有找到匹配函数;3) 多个重载函数符合条件(歧义匹配)。
匹配重载函数的过程:
1)寻找最合适的;2)通过合理转换的匹配(参数的升级转换,如char->int);
3)通过强制的标准转换(如int->double);4) 当以上都没有找到,C++会遍历用户自定义函数;
歧义匹配属于编译运行错误。
处理歧义匹配:
1)定义一个新的重载函数;
2)显式转换歧义的参数到确定的类型;
小结:函数调用会明显降低函数的灵活性,同时附带少许的风险;函数重载或许比较复杂,但非常实用。
8. 默认参数
默认参数,即函数的形参已经赋予初始值。
默认参数是非常出色的选择,当函数需要的默认的值,用户可以也不需要修改;
注意:多于多个默认值,不能跳过赋值;
A) 所有的默认参数必须是由右到左的;B) 最右边的默认值是最常覆盖修改的;C) 默认值不能作为函数重载的标志。
9. 函数指针
函数指针是比较高级的话题;对于数组名是一个地址,那么函数名可以理解是函数的地址;
函数调用时,首先解引用函数名(即函数地址),获取函数的地址入口,才开始执行;
函数指针即指针指向函数的地址,函数指针可以重定向:
因为()的优先级比*高,所以函数指针必须加括号:
注意:函数指针的签名(包括参数、返回值等)必须匹配指向的函数的签名。
函数指针调用,就如指向的函数的隐式调用一样,如pFoo() ;
函数指针的通常应用是函数实现特定的功能,但你想用户可以自定功能的实现;
如选择排序:
10. 栈和堆
程序使用的内存区域分4个部分:
A)代码区:编译的程序放置的地方;B)全局区:存放全局变量的地方;C)堆:动态分配的变量存放地方;D)栈:形参和局部变量存放的地方。
1)堆-自由存放区,是动态分配的一个巨大缓冲池;
必须知道:顺序的存储请求,不一定得到实际上的顺序存储区域;
当动态分配的内存释放,返回堆,作为新的可以分配的内存;
2)栈:只能从顶部取出和放入的操作:
top()、pop()、push()是常用的操作;
栈是first in, last out(FILO)的结构;
当栈的的存储区域已经满了,就会出现溢出。
不必要详细了解栈的工作细节。
11. 递归
C++的递归就是函数的自身调用。
递归必须有终止条件,否则就为无限递归。如:
再如:求1到nValue的和:
示例3:Fibonacci数:
12. 命名空间
命名空间概念,确切来说不归入函数这部分,但是十分重要的概念。
程序中出现标识符(变量或函数名)在相同的范围,即命名冲突。
这时,可以使用命名空间来解决,通过全局::运算符,来调用所需函数或变量;
亦可以通过using关键字,引入命名空间。
13. 捕捉错误
错误包括断言、错误、退出和异常。
编程中,你不可能避免错误,包括语法和词义错误;
语法错误-没有按照相应的语言的语法格式编程;
词义错误-程序没有按照编程人员的意愿,实现目标;不能被编译器捕捉,
A)逻辑错误;B)冒犯性假设错误。
处理:
A)防御错误;B)探测错误;
2)断言-Assert
如果断言的条件是true,程序不过处理,如果断言的条件是false,则程序发出错误异常消息并终止程序;
至此,C++面向过程编程已学习完毕,后面部分为C++面向对象编程的学习。Have Fun!!!!!!!
【免责特此声明:
1)本内容可能是来自互联网的,或经过本人整理的,仅仅代表了互联网和个人的意见和看法!
2)本内容仅仅提供参考,任何参考该内容造成任何的后果,均与原创作者和本博客作者无关!】
相关文章推荐
- C/C++学习笔记1 - 深入了解scanf()/getchar()和gets()等函数
- C++学习2:main()函数深入学习
- 深入学习C++中的函数概念
- C++学习(九)函数深入
- C/C++学习笔记1 - 深入了解scanf()/getchar()和gets()等函数
- C/C++学习笔记1 - 深入了解scanf()/getchar()和gets()等函数(原创)
- C/C++学习笔记1 - 深入了解scanf()/getchar()和gets()等函数
- [C++再学习系列] 深入new/delete:New的3种形态
- C++学习总结系列--函数部分
- [C++学习历程]基础部分 C++中的函数学习
- C++学习摘要之四:虚函数和多态
- c++学习笔记(返回引用的函数)
- C++ STL学习之三:序列式容器deque深入学习
- PKU C++程序设计实习 学习笔记3 多态与虚函数
- 学习 FC++:C++ 函数编程库
- C/C++语言函数学习(4)字符串处理函数
- C++学习笔记-----永远不要在派生类中改变虚函数的默认参数值
- C++学习笔记二十 - 调用后面的函数需要先声明
- 【C++ STL学习之三】容器deque深入学习
- C++学习笔记之函数指针