《C++ Primer》第6章 函数(一)

参考资料:

  • 《C++ Primer》第5版
  • 《C++ Primer 习题集》第5版

6.1 函数基础(P182)

典型的函数定义包括:返回类型( return type )、函数名字、0 个或多个形参( parameter )组成的列表、函数体。其中函数体为语句块

我们通过调用运算符执行函数。调用运算符的形式是一对圆括号,作用于函数或指向函数的指针,圆括号之内是实参(argument)列表,实参用来初始化函数的形参。调用表达式结果的类型就是函数的返回类型。

调用函数

函数调用完成两项工作:

  1. 用实参初始化函数的形参。
  2. 将控制权移交到被调用函数。

形参和实参

实参和形参一一对应,但没有规定求值顺序。

实参的类型必须与对应的形参匹配,实参的数量和形参一致。

函数的形参列表

形参列表可以为空,但不能省略:

void f1() { /* ... */ }
void f2(void) { /* ... */ }

每个形参都是含有一个声明符的声明,函数最外层作用域的局部变量不能和函数形参同名。

形参名不是必须的,如果某个形参在函数中不会被用到,可以不对其命名。

函数的返回类型

函数的返回类型不可以是数组或函数(因为这两种类型不支持拷贝操作?),但可以是指向数组或函数的指针。

6.1.1 局部对象(P184)

  • 名字的作用域是程序文本的一部分,名字在其中可见
  • 对象的生命周期是程序执行过程中该对象存在的一段时间。

形参和函数体内部定义的变量称为局部变量(local variable),这些变量只在函数内部可见,且会隐藏外层作用域中的同名变量。

在所有函数体之外定义的对象在程序启动时被创建,直到程序结束才会销毁

自动对象

我们把只存在于块执行期间的对象称为自动对象(automatic object)

局部静态对象

如果想令局部变量的生命周期贯穿函数调用及之后的时间,可以使用 static 将其定义成局部静态对象(local static object)。局部静态对象在程序第一次经过其定义语句时初始化,直到程序结束才销毁:

int count_calls(){static int cnt = 0;return ++cnt;
}

如果局部静态变量没有显式的初始值,将执行值初始化

6.1.2 函数声明(P186)

函数只能定义一次,但可以声明很多次。函数的声明和定义非常相似,区别在于无须函数体也无须形参的名字,用分号代替即可。

函数最好在头文件中声明,在源文件中定义。

6.1.3 分离式编译(P186)

C++ 语言支持分离式编译,即把程序分隔到多个文件中,每个文件独立编译。

编译和链接多个源文件

6.2 参数传递(P187)

形参的初始化机制和变量初始化一样,如果形参是引用类型,它将绑定到对应的实参上,否则将实参的值拷贝给形参。

6.2.1 传值参数(P187)

指针形参

指针形参初始化时和其他非引用类型一样执行拷贝操作,拷贝之后两个不同的指针指向同一个对象。

在 C++ 中,建议使用引用形参代替指针形参

6.2.2 传引用参数(P188)

使用引用避免拷贝

当某些对象拷贝效率较低不支持拷贝时,可以使用引用形参访问该类的对象。如果函数无需改变引用形参的值,最好将其声明为常量引用。

使用引用形参返回额外信息

6.2.3 const形参和实参(P190)

当形参具有顶层 const 属性时,传入常量还是非常量都是可以的,换句话说,形参中的顶层 const 属性在初始化时被忽略了。

C++ 允许我们定义若干相同名字的函数,前提是这些函数应有不同的形参列表:

void func(const int ci);
void func(int i);     // 错误

指针或引用形参与const

尽量使用常量引用

把函数不会改变的形参定义成普通引用是一种常见的错误,这样做会让人误认为函数可以修改这个对应实参的值,同时还会限制能接受的实参类型(不能把 const 对象、字面值、需要类型转换的对象传递给普通引用形参上)。

6.2.4 数组形参(P193)

由于数组不支持拷贝,所以数组不能作为函数的返回类型;由于数组名通常会转换成指针,所以我们向函数传递一个数组时,实际上传递的是指向首元素的指针。

尽管不能通过值传递的方式传递数组,但 C++ 允许我们把形参写成数组形式:

// 下面三个函数是等价的,唯一的形参都是const int*
void print(const int*);
void print(const int[]);
void print(const int[10]);    // 这里的10其实没啥用

无论 print 函数使用上述的哪种方式声明,编译器只检查传入的参数是否是 const int* 。也就是说,将数组当作实参传递给函数时,会自动转化为指向首元素的指针。

使用标记指定数组长度

数组本身包含一个结束标记,如 C 风格字符串。

使用标准库规范

利用 begin()end() 传递数组的首元素指针和尾后指针。

显式传递一个表示数组大小的形参

数组形参和const

当不需要改变数组元素时,应该将数组形参设为指向 const 的指针。

数组引用形参

当形参为数组的引用时,数组的维度就成了类型的一部分:

void print(int (&arr)[10]);    // 限制实参必须为维度为10的数组

传递多维数组

由于 C++ 中多维数组实际上是数组的数组,所以多维数组除第一维外均不可以忽略:

void print(int (*matrix)[10]);
void print(int matrix[][10]);    // 因为编译器会忽略第一个维度,所以声明时最好不写

6.2.5 main:处理命令行选项(P196)

int main(int argc, char *argv[]) { ... }

argc 表示 argv 数组中字符串的数量。当实参传递给 main 函数后,argv 的第一个元素指向空串或程序的名字,接下来的元素依次为命令行提供的实参,最后一个指针的下一个元素为 0 。如命令:

prog -d -o ofile data0

argv 数组中的内容为:

argv[0] = "prog";    // 程序名,也可能是空串
argv[1] = "-d";     // 实参实际上argv[1]开始
argv[2] = "-o";
argv[3] = "ofile";
argv[4] = "data0";
argv[5] = 0;

6.2.6 含有可变形参的函数(P197)

initializer_list实参

如果所有实参类型相同,但数量不固定,我们可以使用名为 initializer_list 的标准库类型作为形参。initializer_list 定义在同名头文件中

image-20231012204644635

initializer_list 中的元素永远是常量。

void error_msg(initializer_list<string> il){for(auto beg = il.begin();beg!=il.end();++beg){cout << *beg << ' ';}cout << endl;
}// 调用方式
error_msg({"functionX", expected, actual});

省略符形参

省略符形参是为了便于 C++ 程序访问某些 C代码而设置的,省略符只能出现在形参列表的最后一个位置:

void foo(pram_list, ...);
void foo(...);

6.3 返回类型和return语句(P199)

return;
return expression;

6.3.1 无返回值函数(P200)

没有返回值的语句只能用于返回值为 void 的函数中。返回值为 void 的函数最后一句后面会隐式执行 return

返回值为 void 的函数也能返回使用第二种类型的 return 语句,但 expression 必须为另一个返回 void 的函数。

6.3.2 有返回值函数(P200)

在含有 return 语句的循环后面也应该有一条 return 语句。如果没有的话该程序就是错误的,而许多编译器无法发现这个错误。

值是如何被返回的

返回的值用于初始化调用点的一个临时量

返回值也可以是引用类型:

const string &shorterString(const string s1, const string s2){return s1.size() <= s2.size() ? s1 : s2;
}

不要返回局部对象的引用或指针

函数完成后,它所占用的空间也会被释放掉。

返回类类型的函数和调用运算符

调用运算符的优先级和点运算符和箭头运算符相同,满足左结合律。

引用返回左值

函数的返回类型决定函数调用是否为左值,调用一个返回引用的函数得到左值,其他返回类型得到右值。

列表初始化返回值

C++11 规定,函数可以返回花括号包围的值的列表。如果列表为空,临时量执行值初始化。

vector<string> example{return {'hello', 'world'};
}

主函数main的返回值

main 函数是唯一返回类型不是 void 但可以没有 return 语句的函数,编译可以隐式插入一条返回 0 的 return 语句。

main 函数返回 0 表示执行成功,其他值表示执行失败。cstdlib 头文件定义了 EXIT_FALLUREEXIT_SUCCESS 两个预处理变量,用来表示 main 函数执行的失败与成功。

递归

main 函数不能调用自己。

6.3.3 返回数组指针(P205)

虽然函数不能返回数组,但可以返回数组的指针或引用:

typedef int arrT[10];    // arrT是含有是个整数的数组类型
arrT* func(int i);    // 使用类型别名可以简化表达式

func 函数接受一个 int 实参,返回一个指向包含 10 个 int 的数组的指针。

声明一个返回数组指针的函数

如果在声明 func 函数时不想使用类型别名,则可以按照如下方式声明:

int (*func(int i))[10];

数组的维度必须在名字之后,而函数的形参列表应该紧跟在函数名字后面,所以数组维度要写在形参列表后面;(*func(int i)) 外侧的括号不能省略,否则函数的返回类型将是指针的数组,这显然是不合法的。

使用尾置返回类型

在 C++11 新标准中,可以使用尾置返回类型简化 func 的声明:

auto func(int i) -> int(*)[10];

任何函数都可以使用尾置返回,为了表示函数真正的返回类型在形参列表之后,我们在本应出现返回类型的地方放置一个 auto

使用decltype

int arr[10] = {};decltype(arr) *func(int i);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/128883.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Redis常见的全局命令

Redis中最核心的两个命令set和get 两个最核心的命令就是get和set. redis是按照键值对的方式来存储数据的,所以set就表示把key-value存储进去,get表示根据key来查询对应的value. 需要注意的是,必须进入redis客户端才能输入redis命令. 此处的key和value都是字符串类型.对于上述…

致远OA wpsAssistServlet任意文件上传漏洞复现 [附POC]

文章目录 致远OA wpsAssistServlet任意文件上传漏洞复现 [附POC]0x01 前言0x02 漏洞描述0x03 影响版本0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现 0x06 修复建议 致远OA wpsAssistServlet任意文件上传漏洞复现 [附POC] 0x01 前言 免责声明&#xff1a;请勿利用…

【行云流水线实践】基于“OneBuild”方法对镜像进行快速装箱 | 京东云技术团队

在云原生领域&#xff0c;无论使用哪种编排调度平台&#xff0c;Kubernetes&#xff0c;DockerSwarm&#xff0c;OpenShift等&#xff0c;业务都需要基于镜像进行交付&#xff0c;我们在内部实践“Source-to-image”和链式构建&#xff0c;总而总结出“OneBuild”模式。 其核心…

VS2022安装时碰到VsWebProtocolSelector.Msi包安装错误,2330code解决方法

未能安装包“Microsoft.VisualStudio.VsWebProtocolSelector.Msi,version17.8.34129.139”。 搜索 URL https://aka.ms/VSSetupErrorReports?qPackageIdMicrosoft.VisualStudio.VsWebProtocolSelector.Msi;PackageActionInstall;ReturnCode2330 详细信息 …

C++——定义一个 Book(图书)类

完整代码&#xff1a; /*定义一个 Book(图书)类&#xff0c;在该类定义中包括数据成员和成员函数 数据成员&#xff1a;book_name &#xff08;书名&#xff09;、price(价格)和 number(存书数量)&#xff1b; 成员函数&#xff1a;display()显示图书的 情况&#xff1b;borro…

Spring面试题:(二)基于xml方式的Spring配置

xml配置Bean的常见属性 id属性 name属性 scope属性 lazy-init属性 init-method属性和destroy属性 initializingBean方法 Bean实例化方式 ApplicationContext底层调用BeanFactory创建Bean&#xff0c;BeanFactory可以利用反射机制调用构造方法实例化Bean&#xff0c;也可采用工…

Apollo云实验:使用Sim control仿真自动驾驶

使用Sim control仿真自动驾驶 概述Sim control仿真自动驾驶启动DreamView仿真系统 实验目的福利活动 主页传送门&#xff1a;&#x1f4c0; 传送 概述 自动驾驶汽车在实现落地应用前&#xff0c;需要经历大量的道路测试来验证算法的可行性和系统的稳定性&#xff0c;但道路测试…

关于Linux下排查C++进程Segment fault问题的步骤

C 中出现Segment问题的常见原因有: 如果要定位Segment fault问题&#xff0c;需要进行如下几步&#xff1a; gdb your_program(gdb) break main(gdb) run(gdb) backtrace同时要在CMakeLists.txt文件中配置编译时启用符号调试信息&#xff0c; 在C或者C中的设置分别如下&#x…

Pytest UI自动化测试实战实例

环境准备 序号库/插件/工具安装命令1确保您已经安装了python3.x2配置python3pycharmselenium2开发环境3安装pytest库pip install pytest4安装pytest -html 报告插件pip install pytest-html5安装pypiwin32库(用来模拟按键)pip install pypiwin326安装openpyxl解析excel文件库p…

R语言使用surveyCV包对NHANES数据(复杂调查加权数据)进行10折交叉验证

美国国家健康与营养调查&#xff08; NHANES, National Health and Nutrition Examination Survey&#xff09;是一项基于人群的横断面调查&#xff0c;旨在收集有关美国家庭人口健康和营养的信息。 地址为&#xff1a;https://wwwn.cdc.gov/nchs/nhanes/Default.aspx 既往咱们…

Linux 服务器 Oracle19C安装

原文:【精选】Oracle | CentOS7安装Oracle19c数据库(RPM包)_oracle-database-preinstall-19c-1.0-1.el7.x86_64.rp_Thorolds Deer的博客-CSDN博客 下载 第一个软件包:Oracle Database 19c Download for Linux x86-64 第二个包:Oracle Linux 7 (x86_64) Latest | Oracle,…

免费(daoban)gpt,同时去除广告

一. 内容简介 免费(daoban)gpt&#xff0c;同时去除广告&#xff0c;https://chat18.aichatos.xyz/&#xff0c;也可当gpt用&#xff0c;就是有点广告&#xff0c;大家也可以支持一下 二. 软件环境 2.1 Tampermonkey 三.主要流程 3.1 创建javascript脚本 点击添加新脚本 …

香港服务器不稳定的几种情况

​  近年来&#xff0c;随着互联网的迅猛发展&#xff0c;香港作为一个重要的网络枢纽地区&#xff0c;扮演着连接中国内地和国际网络的重要角色。一些用户表示在使用香港服务器时可能会遇到不稳定的情况&#xff0c;导致访问困难、加载缓慢甚至无法连接。 为什么香港服务器会…

uni-app 开发的H5 定位功能部署注意事项

一、H5部署的时候&#xff0c;如果设计到定位功能&#xff0c;需要注意以下几点 1、打包部署的时候需要在Web配置-定位和地图里面勾选一个地图&#xff0c;并配置key 2、打包部署需要域名是https协议的&#xff0c;大多数现代浏览器要求在HTTPS协议下才能够访问地理位置信息&a…

CentOS 搭建 Hadoop3 高可用集群

Hadoop FullyDistributed Mode 完全分布式 spark101spark102spark103192.168.171.101192.168.171.102192.168.171.103namenodenamenodejournalnodejournalnodejournalnodedatanodedatanodedatanodenodemanagernodemanagernodemanagerrecource managerrecource managerjob hist…

【Spring Boot】发送邮件功能

发送邮件功能 一.pom.xml文件添加邮件依赖二.发送邮件信息&#xff08;1&#xff09;固定配置在application.yml&#xff08;2&#xff09;发送邮箱配成活&#xff08;3&#xff09;底层发送邮件方法&#xff08;4&#xff09;QQ邮箱开通smtp服务&#xff08;5&#xff09;网易…

低代码平台如火如荼,告诉我它具体能做什么?

目录 一、前言 二、低代码平台 三、低代码平台的优劣 四、低代码能解决哪些问题&#xff1f; 五、好用且强大的低代码平台 六、结语 一、前言 目前低代码平台如火如荼。这一新兴技术为企业提供了一种高效、灵活、快速开发应用程序的方法&#xff0c;并在短时间内取得了巨大成功…

体验SOLIDWORKS钣金切口工具增强 硕迪科技

在工业生产制造中&#xff0c;钣金加工是一种常用的加工方式&#xff0c;在SOLIDWORKS2024新版本中&#xff0c;钣金切口工具再次增强了&#xff0c;从SOLIDWORKS 2024 开始&#xff0c; 您可以使用切口工具在空心或薄壁圆柱体和圆锥体中生成切口。 只需在现有空心或薄壁圆柱体…

Vue监听事件

一、问题场景 项目有个需求&#xff0c;在登录页面&#xff0c;输入好账号密码后&#xff0c;直接可以点击回车就能够登录&#xff0c;效果和点击登录按钮一样&#xff0c;登录页面源码如下 <template><body id"poster"><el-form class"login-…

基于ThinkPHP+MySQL实现的通用的PHP网站后台管理系统

caozha-admin 后台管理框架 1.8.3 caozha-admin是一个通用的PHP网站后台管理框架&#xff0c;基于开源的ThinkPHP开发&#xff0c;特点&#xff1a;易上手&#xff0c;零门槛&#xff0c;界面清爽极简&#xff0c;极便于二次开发。 基础功能 1、系统设置 2、管理员管理 3、…