函数
C++ 是一种静态强类型语句(第 2.3 节),对于每一次的函数
调用,编译时都会检查其实参。
形参的初始化与变量的初始化一样:如果形参具有非引用类型,
则复制实参的值,如果形参为引用类型(第 2.5 节),则它只
是实参的别名。
非引用形参表示对应实参的局部副本。对这类形参的修改仅仅
改变了局部副本的值。一旦函数执行结束,这些局部变量的值
也就没有了。
函数的形参可以是指针,此时将复制实参指针。
因为在 C 语言中,具有 const 形参或非 const 形参的函数并无区别。
复制实参并不是在所有的情况下都适合,不适宜复制实参的情况包括:
当需要在函数中修改实参的值时。
当需要以大型对象作为实参传递时。对实际的应用而言,复制对象所付出
的时间和存储空间代价往往过在。
当没有办法实现对象的复制时。
对于上述几种情况,有效的解决办法是将形参定义为引用或指针类型。
从 C 语言背景转到 C++ 的程序员习惯通过传递指针来实现对实参的访问。在 C++ 中,使用引用形参则更安全和更自然。
引用形参的另一种用法是向主调函数返回额外的结果。
如果使用引用形参的唯一目的是避免复制实参,则应将形参定义为 const 引用。
问题的关键是非 const 引用形参只能与完全同类型的非 const 对象关联。
应该将不修改相应实参的形参定义为 const 引用。如果将这样的形参定义
为非 const 引用,则毫无必要地限制了该函数的使用。
应该将不需要修改的引用形参定义为 const 引用。普
通的非 const 引用形参在使用时不太灵活。这样的形
参既不能用 const 对象初始化,也不能用字面值或产
生右值的表达式实参初始化。
int main(int argc, char *argv[]) { ... }或者int main(int argc, char **argv) { ... }
第一个形参 argc 则用于传递该数组中字符串的个数。
当将实参传递给主函数 main 时,argv 中的第一个字符串(如果有的话)
通常是程序的名字。接下来的元素将额外的可选字符串传递给主函数 main。
7.2.7. 含有可变形参的函数
C++ 中的省略符形参是为了编译使用了 varargs 的 C 语言程序。
省略符暂停了类型检查机制。它们的出现告知编译器,当调用函数时,可以
有 0 或多个实参,而实参的类型未知。省略符形参有下列两种形式:
void foo(parm_list, ...);
void foo(...);
一般情况下,返回类型是 void 的函数使用 return 语句是为了引起函数的
强制结束,这种 return 的用法类似于循环结构中的 break 语句的作用。
允许主函数 main 没有返回值就可结束。
如果程序控制执行到主函数 main 的最后一个语句都还没有返回,那么编译器会隐式地插入返回 0 的语句。
函数的返回值用于初始化在调用函数处创建的临时对象。在求解表达式时,
如果需要一个地方储存其运算结果,编译器会创建一个没有命名的对象,这就是
临时对象。
在英语中,C++ 程序员通常用 temporary 这个术语来代替 temporary object。
理解返回引用至关重要的是:千万不能返回局部变量的引用。
当函数执行完毕时,将释放分配给局部对象的存储空间。此时,对局部对象
的引用就会指向不确定的内存。
给函数返回值赋值可能让人惊讶,由于函数返回的是一个引用,因此这是正
确的,该引用是被返回元素的同义词。如果不希望引用返回值被修改,返回值应该声明为 const。
只有当定义它的函数被调用时才存在的对象称为自动对象。
局部变量所对应的自动对象在函数控制经过变量定义语句时创建。
形参也是自动对象。形参所占用的存储空间在调用函数时创建,而在函数结束时撤销。
一个变量如果位于函数的作用域内,但生命期跨越了这个函数的多次调用,
这种变量往往很有用。则应该将这样的对象定义为 static(静态的)。
这种对象一旦被创建,在程序结束前都不会撤销。当定义静态局
部对象的函数结束时,静态局部对象不会撤销。在该函数被多次调用的过程中,
静态局部对象会持续存在并保持它的值。
7.6. 内联函数
一般来说,内联机制适用于优化小的、只有几行的而且经常被调用的函数。
大多数的编译器都不支持递归函数的内联。
内联函数应该在头文件中定义,这一点不同于其他函数。
inline 函数的定义对编译器而言必须是可见的,以便编译器能够在调用点
内联展开该函数的代码。此时,仅有函数原型是不够的。
类的成员函数可以访问该类的 private 成员。
每个成员函数都有一个额外的、隐含的形参 this。
用这种方式使用 const 的函数称为常量成员函数。
const 对象、指向 const 对象的指针或引用只能用于调用其
const 成员函数,如果尝试用它们来调用非 const 成员函数,
则是错误的。
在成员函数中,不必显式地使用 this 指针来访问被调用函数所属对象的成员。
对这个类的成员的任何没有前缀的引用,都被假定为通过指针 this 实现的引用。
在类的定义外面定义成员函数必须指明它们是类的成员
函数名:
Sales_item::avg_price
使用作用域操作符指明函数 avg_price 是在类 Sales_item 的作用域范围内定义的。
在任何函数定义中,返回类型和形参表必须和函数声明(如果有的话)一致。对于成
员函数,函数声明必须与其定义一致。如果函数被声明为 const 成员函数,那
么函数定义时形参表后面也必须有 const。
构造函数是特殊的成员函数
Sales_item(): units_sold(0), revenue(0.0) { }
在冒号和花括号之间的代码称为构造函数的初始化列表。
构造函数的初始化列表为类的一个或多个数据成员指定初值。它跟在构造函数的形参表之后,以冒号开关。
合成的默认构造函数一般适用于仅包含类类型成员的类。而对
于含有内置类型或复合类型成员的类,则通常应该定义他们自
己的默认构造函数初始化这些成员。
出现在相同作用域中的两个函数,如果具有相同的名字而形参表不同,则称为重载函数。
typedef 给已存在的数据类型提供别名,但并没有创建新的数据类型。
7.8.1. 重载与作用域
在函数中局部声明的名字将屏蔽在全局作用域内声明的同名名字。
一般来说,局部地声明函数是一种不明智的选择。函数的声明
应放在头文件中。
在 C++ 中,名字查找发生在类型检查之前。
在实际应用中,调用重载函数时应尽量避免对实参做强制类型转换:
需要使用强制类型转换意味着所设计的形参集合不合理。
7.9. 指向函数的指针
函数指针是指指向函数而非指向对象的指针。像其他指针一样,函数指针也指向某个特定的类型。函数类型由其返回类型以及形参表确定,而与函数名无关.
bool (*pf)(const string &, const string &);
这个语句将 pf 声明为指向函数的指针,它所指向的函数带有两个 const
string& 类型的形参和 bool 类型的返回值。
typedef bool (*cmpFcn)(const string &, const string &);
该定义表示 cmpFcn 是一种指向函数的指针类型的名字。该指针类型为“指
向返回 bool 类型并带有两个 const string 引用形参的函数的指针”。在要使
用这种函数指针类型时,只需直接使用 cmpFcn 即可,不必每次都把整个类型声
明全部写出来。
可使用函数名对函数指针做初始化或赋值.
bool lengthCompare(const string &, const string &);
cmpFcn pf1 = 0;// ok: unbound pointer to function
cmpFcn pf2 = lengthCompare; // ok: pointer type matches function's type
pf1 = lengthCompare; // ok: pointer type matches function's type
pf2 = pf1; // ok: pointer types match type
直接引用函数名等效于在函数名上应用取地址操作符
cmpFcn pf1 = lengthCompare;
cmpFcn pf2 = &lengthCompare;
函数指针只能通过同类型的函数或函数指针或 0 值常量表达
式进行初始化或赋值。
function and pointer types match exactly,返回值和参数都要一致。
指向函数的指针可用于调用它所指向的函数。可以不需要使用解引用操作
符,直接通过指针调用函数:
cmpFcn pf = lengthCompare;
lengthCompare("hi", "bye"); // direct call
pf("hi", "bye");
// equivalent call: pf1 implicitly
dereferenced
(*pf)("hi", "bye");
// equivalent call: pf1 explicitly
dereferenced
如果指向函数的指针没有初始化,或者具有 0 值,则该指针不
能在函数调用中使用。只有当指针已经初始化,或被赋值为指
向某个函数,方能安全地用来调用函数。
int (*ff(int))(int*, int);
要理解该声明的含义,首先观察:
ff(int)
将 ff 声明为一个函数,它带有一个 int 型的形参。该函数返回
int (*)(int*, int);
它是一个指向函数的指针,所指向的函数返回 int 型并带有两个分别是
int* 型和 int 型的形参。
使用 typedef 可使该定义更简明易懂:
// PF is a pointer to a function returning an int, taking an int*
and an int
typedef int (*PF)(int*, int);
PF ff(int); // ff returns a pointer to function
允许将形参定义为函数类型,但函数的返回类型则必须是指向
函数的指针,而不能是函数。
指向重载函数的指针
C++ 语言允许使用函数指针指向重载的函数:
extern void ff(vector<double>);
extern void ff(unsigned int);
void (*pf1)(unsigned int) = &ff; // ff(unsigned)
指针的类型必须与重载函数的一个版本精确匹配。如果没有精确匹配的函
数,则对该指针的初始化或赋值都将导致编译错误
分享到:
相关推荐
【C++学习笔记【原创】】是一份作者个人长期积累的C++学习心得与经验总结,旨在为初学者提供一个参考的学习路径。这份笔记涵盖了C++的基础知识、编程技巧以及函数语法等多个方面,帮助读者逐步掌握这门强大的编程...
这份笔记结合了书本内容的摘录和作者个人的理解,其中包含了7章原创内容以及14章从CSDN网站上整理摘抄的部分,这些章节可能有所重叠,但无疑为学习者提供了丰富的资源。 C++模板是C++语言中的一个强大工具,它允许...
了解函数的声明、定义、参数传递以及如何返回值是学习C++的关键步骤。 3. **数组与指针**:数组是一组相同类型的数据集合,而指针是存储内存地址的变量。理解指针的概念,掌握指针运算和动态内存分配(如malloc, ...
### iOS开发教程(大神原创笔记)核心知识点详解 #### 一、Unix相关知识点 **1. Unix指令:** - **pwd**:用于显示当前所在目录的位置。 - **ls**:列出当前目录下的所有文件及文件夹。 - **ls –l**:以详细...
最近开始学习非关系型数据库MongoDB,却在博客园上找不到比较系统的教程,很多资料都要去查阅英文网站,效率比较低下。本人不才,借着自学的机会把心得体会都记录下来,方便感兴趣的童鞋分享讨论。部分资源出自...
综上所述,这个压缩包"PAT甲级所有代码.7z"是一个宝贵的资源,对于准备参加PAT甲级竞赛或提升C++编程和算法能力的学习者来说,可以从中学习到实际的编程技巧,了解如何将理论知识应用于实践,同时也可以通过分析和...
陌溪的学习笔记 关于我 陌溪 是一个从三本院校一路摸滚翻爬上来的程序员。目前就职于 字节跳动的Data广告部门,是字节跳动全线产品的商业变现研发团队。这两天创建了一个 微信公众号【陌溪教你学编程】,未来将会在...
总的来说,这个压缩包提供了一个完整的、原创的记事本项目的实例,对于想要学习编程尤其是文本编辑器开发的初学者来说,是一个宝贵的资源。通过这个项目,你可以了解到软件的基本架构、文件处理、用户界面设计等多个...
由于本人水平有限,仓库中的知识点有来自本人原创、读书笔记、书籍、博文等,非原创均已标明出处,如有遗漏,请 向issue 提出。此仓库引用于issue! 只面向初学者用于学习参考~ :bookmark_tabs: 目录 :plus: C/C++ ...
描述:"大神原创的iOS开发教程,内容全面,覆盖OC及iOS开发全部技术细节内容,值得认真学习" 标签:"iOS 移动开发 Objective-C iOS开发 教程" 部分内容: 1. iOS开发基础介绍:开发者拥有丰富的Android、iOS、PHP和...
7. **项目或研究**:可能包含学生或教师进行的原创性研究,比如基于C++的软件开发项目。 8. **源代码**:如果涉及软件开发,这里可能会有C++项目的源代码,展示实际编程实践。 9. **论坛或讨论区**:可能有一个交互...
因此我在做三维姿态上位机过程中,又学习了一下SharpGL,当然很感谢官方的源码例程,基本所有的操作都是跟着官方例程来的。在这里分享一下: ———————————————— 版权声明:本文为CSDN博主「川北97...
- 学生按成绩排名,前70名晋级,同时设有奖励机制,包括个人操行成绩加分和实物奖励(如笔记本),并激励班级参与,以提升整体学习氛围。 2. **代码书写阶段**: - 晋级的学生可自由组队参赛,每队1至3人,可以...
标题 "自己开发的俄罗斯方块" 暗示了这是一个由个人或小团队独立完成的电子游戏项目,其中主要的编程语言可能是C++、Python、Java等,因为这些语言广泛用于游戏开发。俄罗斯方块是一款经典的休闲游戏,其基本原理是...
- **营造良好氛围**:构建一个有利于学习和研究的良好环境,提高教学质量。 #### 二、大赛流程 1. **资格赛阶段** - **时间**:待定。 - **形式**:笔试,包含客观题。 - **参赛资格**:面向全体在校生,可以...
5. **最短路径和传递闭包**:最短路径问题的目标是找到两个节点之间的最短路径,通常采用Dijkstra算法或Bellman-Ford算法。传递闭包是指图中所有节点之间可到达性的完整表示,常用于解决图论中的多种问题。 6. **...
它分为多个级别,如初级、中级和高级,涵盖C/C++、Java、Python等编程语言,以及数据结构、算法分析等多个IT领域的知识。试题通常会包括选择题、填空题和编程题,涉及的内容广泛且深入。 "蓝桥杯试题及参考答案欢迎...
中国科学技术大学课程资源本仓库收录中国科学技术大学众多课程资源的笔记,总结,经验等学生原创内容目录索引版权说明本仓库分享资料遵守其创作者之规定,由同学自愿投稿,仅接收学生原创的或获得授权的资源。...