博主在读机器人研究生,目前研一。对计算机后端感兴趣,喜欢
c
,
g
o
,
p
y
t
h
o
n
,
目前熟悉
c
,
g
o
语言,数据库,网络编程,了解分布式等相关内容
\textcolor{orange}{博主在读机器人研究生,目前研一。对计算机后端感兴趣,喜欢c++,go,python,目前熟悉c++,go语言,数据库,网络编程,了解分布式等相关内容}
博主在读机器人研究生,目前研一。对计算机后端感兴趣,喜欢c++,go,python,目前熟悉c++,go语言,数据库,网络编程,了解分布式等相关内容
📃个人主页:
\textcolor{gray}{个人主页:}
个人主页: 小呆鸟_coding
🔎支持
:
\textcolor{gray}{支持:}
支持:
如果觉得博主的文章还不错或者您用得到的话,可以免费的关注一下博主,如果三连收藏支持就更好啦
\textcolor{green}{如果觉得博主的文章还不错或者您用得到的话,可以免费的关注一下博主,如果三连收藏支持就更好啦}
如果觉得博主的文章还不错或者您用得到的话,可以免费的关注一下博主,如果三连收藏支持就更好啦👍
就是给予我最大的支持!
\textcolor{green}{就是给予我最大的支持!}
就是给予我最大的支持!🎁
💛本文摘要💛
本专栏主要是对c++ primer这本圣经的总结,以及每章的相关笔记。目前正在复习这本书。同时希望能够帮助大家一起,学完这本书。 本文主要讲解第6章 函数 文章目录
c++ primer 第五版 系列文章:可面试可复习
第2章 变量和基本类型
第3章 字符串、向量和数组
第4章 表达式
第5章 语句
第6章 函数
第8章 IO库
第9章 顺序容器
第10章 泛型算法
第11章 关联容器
第12章 动态内存
第13章 拷贝控制
第 14章 重载运算符
第15章 面向对象程序设计
第 16章 模板与泛型编程
- 本章主要介绍函数传参及函数返回结果、函数重载、重载函数应该选择哪个进行调用。
🎯6.1 函数基础
- 通过调用
运算符 ()
来执行函数。
函数调用完成俩项工作:
用实参初始化函数对应的形参。
将控制器转移给被调用函数。
此时主调函数被中断,被调函数开始执行。
函数执行的第一步:隐式地定义并初始化它的形参。实参是形参的初始值,第一个实参初始化第一个形参。
return 语句完成俩项工作:
返回return 语句中的值
将控制权从被调函数转移回主调函数
形参
- 实参是形参的初始值。
- 实参的类型与形参类型匹配,或者可以转换成形参类型。
- 可以没有形参名,但是函数无法使用未命名的形参,即使形参未命名,也要传入实参。
返回类型
- 函数返回类型不能是
数组类型
或者函数类型
. - 但是可以是
数组指针
或函数指针
🎨6.1.1 局部对象
名字有作用域,对象有生命周期
- 形参和函数体
内部定义
的变量统称为局部变量
形参属于自动对象:
- 函数开始时为形参
申请存储空间
,因为形参定义在函数体作用域之内,函数终止,形参被销毁
- 在所有函数外定义的对象存在于程序的整个执行过程中
局部静态变量
- 在程序的执行路径第一次经过对象定义语句时初始化,直到程序终止被销毁。
- 只存在于
块执行期间的对象
。当块的执行结束后,它的值就变成未定义的了。 - 如果想要局部变量声明周期在
整个程序结束
,可以将局部变量定义成static类型
- 如果局部静态变量没有显式的初始值,将执行值初始化。
🎨6.1.2 函数声明
- 函数的声明和定义唯一的区别是
声明无需函数体,用一个分号替代。
- 函数声明主要用于
描述函数的接口
,也称函数原型。 函数的声明无需形参的名字
(因为声明不包含函数体)。- 函数的三要素:
返回类型
、函数名
、形参类型
。 - 建议在头文件中声明函数,在源文件中定义函数。
🎨6.1.3 分离式编译
分离式编译允许把程序分割到几个文件中,每个文件独立编译。
🎯6.2 参数传递
- 引用传递:又称传引用调用,指形参是
引用类型
,引用形参是它对应的实参的别名。 - 值传递:又称传值调用,指实参的值是通过
拷贝
传递给形参。 - 形参初始化的机理和变量初始化一样。
🎨6.2.1 传值参数
- 当初始化一个非引用类型的变量时,初始值被
拷贝
给变量。 - 函数对形参做的所有操作都
不会影响实参
。 - 指针形参:C++建议使用
引用类型的形参代替指针
。
🎨6.2.2 传引用参数
- 通过使用引用形参,允许函数改变一个或多个实参的值。
- 通过引用可以避免拷贝(如果对象太长,可以使用引用来避免拷贝,拷贝太浪费内存了)
如果无需改变引用形参的值,最好将其声明为常量引用
。- 引用形参直接关联到绑定的对象,而非对象的副本。
使用引用形参可以用于返回额外的信息。
//既返回位置也返回次数,此时可以给函数传入一个额外的引用实参,令其保存字符出现的次数
string::size_type find\_char(const string &s, char c, string::size_type &occurs)
{
auto size = s.size();
occurs = 0;
for (int i = 0; i != s.size(); i ++)
{
if (s[i] == c)
{
if (ret == s.size()) ret = i;
++ occurs;
}
}
return ret; //出现次数通过occurs隐式地返回
}
🎨6.2.3 const 形参和实参
实参初始化形参时以及进行拷贝时,都会忽略掉顶层const
,因此导致void func (const int i)
;调用既可以传入const int
也可以传入int
加深理解:引用是没有顶层 const 的,因此顶层 const 适用于指针及其他类型,对于传值来说传递的是实参的副本,无论如何都不会改变实参,因此形参加不加顶层 const 都是一样的。
void fcn(const int i ){ }
void fcn(int i ){ } //错误:重复定义了fcn(int)
指针或引用形参与const
- 使用非常量初始化一个底层const对象,但是反过来不行。
- 普通引用必须用同类型的对象初始化。
加深理解:不能把普通引用绑定到const 对象上,不能把普通的引用绑定在字面值上。
void reset(int &r) { };
const int i = 10;
reset(i); //错误:不能把普通引用绑定到const 对象上
reset(42); //错误:不能把普通的引用绑定在字面值上
尽量使用常量引用
尽量使用常量引用做形参
(注意常量引用的 const 是底层 const。)- 可以用字面值初始化常量引用
使用常量引用的优点:
想要调用引用版本的reset,只能使用int 类型对象。而不能使用字面值、求值结果为int 的表达式、需要转换的对象或者const int 类型的对象。
- 想要调用指针班的reset 只能使用 int *
不能把 const 对象、字面值或需要类型转换的对象传递给普通的引用形参。但是可以传递给常量引用形参。
注意: 如果函数 a 把形参定义为了常量引用,函数 b 形参是普通引用,那么不能在 a 中使用 b 调用该常量引用形参。
bool is\_sentence(const string &s)
{
//如果在s的末尾有且只有一个句号,则s是一个句子
string :: size_type ctr = 0;
return find\_char(s, '.', ctr) == s.size() - 1 && ctr == 1;
}
错误因为is_sentence是const对象而find_char是普通对象
🎨6.2.4 数组形参
数组的两个特殊性质:不允许拷贝数组、使用数组时常会将其转换成指针
- 因为数组不能进行拷贝,所以无法使用值传递的方式使用数组参数。因为数组会被转换成指针,所实际上传递的是指向数组的首元素指针。
void print(const int\*);
void print(const int[]);
void print(const int[10]);//三种声明等价,数字 10 没有什么实际影响
int i= 0, j[2] = {0, 1};
printf(&i); //正确:&i的类型是int \*
printf(j); //正确:j转换成int \* 并指向j[0]
//传入的是一个数组,那么实参会自动转换成指向数组首元素的指针
使用数组做形参确保数组访问不越界的方法:
- 使用一个结束标记指定数组已结束,典型代表为 C 风格字符串
传递指向数组首元素和尾后元素的指针
显示传递一个表示数组大小的形参
数组引用形参
可以定义数组的引用,但是没有引用数组,因为引用不是一个对象。注意数组的大小是构成数组类型的一部分
func(int &arr[10]); //错误:arr 是引用的数组
func(int (&arr)[10]);//正确:array 是包含 10 个整数的整型数组的引用
int \*arr[10]; //指针的数组
int (\*arr)[10]; //指向数组的指针
🎨6.2.5 main:处理命令行选项
int main(int argc, char *argv[]){...}
- 第一个形参代表
数组中字符串的数量
;第二个形参argv是一个数组,它的元素是指向C风格字符串的指针
。
🎨6.2.6 含有可变形参的函数
无法预知应该向函数传递几个实参,处理不同数量实参的主要方法有俩种:
如果所有实参类型相同,传递一个 initializer_list 类型
使用省略符形参,它可以传递可变数量的实参,注意它一般仅用于与 C 函数交互的接口程序
initializer_list 形参特点
initializer_list
也是一种模板类型,定义在同名的头文件中。initializer_list
与 vector 容器大致相同,但是它的元素都是常量值
。initializer_list
对象只能使用花括号初始化
。- C++ 里的 vector 等各类容器使用列表初始化时本质上都是通过一个采用了 initializer_list 形参的构造函数进行初始化的。
操作 | 解释 |
---|---|
initializer_list<T> lst; | 默认初始化;T 类型元素的空列表 |
initializer_list<T> lst{a,b,c...}; | lst 的元素数量和初始值一样多;lst 的元素是对应初始值的副本;列表中的元素是const 。 |
lst2(lst) | 拷贝或赋值一个initializer_list 对象不会拷贝列表中的元素;拷贝后,原始列表和副本共享元素。 |
lst2 = lst | 同上 |
lst.size() | 列表中的元素数量 |
lst.begin() | 返回指向lst 中首元素的指针 |
lst.end() | 返回指向lst 中微元素下一位置的指针 |
void err\_msg(ErrCode e, initializer_list<string> il){
cout << e.msg << endl;
for (auto bed = il.begin(); beg != il.end(); ++ beg)
cout << \*beg << " ";
cout << endl;
}
err\_msg(ErrCode(404), {"functionX", "okay});
如果向 initailizer_list 形参中传递一个值的序列,必须把序列放在花括号里。
void func(initializer_list<int> il)
func({3,4,5,2});
省略符形参
- 省略符形参仅用于 C 和 C++ 通用的类型,大多数类类型的对象传递给省略符形参都无法正确拷贝。
- 省略符形参只能出现于形参列表的最后一个位置
void func(parm_list,...);
void func(...);
🎯6.3 返回类型和 return 语句
与参数传递一样,不能返回数组,只能返回指向数组的指针或数组的引用
return 俩个作用:
- 返回 return 语句中的值
- 终止当前正在执行的函数,将控制权返回到调用该函数的地方
🎨6.3.1 无返回值函数
- 没有返回值的 return语句只能用在返回类型是 void的函数中
返回 void的函数不要求非得有 return语句。因为它会在最后一句后面隐式地执行 return。
🎨6.3.2 有返回值函数
- return语句的返回值的类型
必须和函数的返回类型相同
,或者能够隐式地转换成函数的返回类型
。 在含有 return 语句的循环和条件后面也应该有一条 return 语句
。- 返回一个值和初始化一个变量或形参的方式一样,返回的值用于初始化调用点的变量。
不要返回局部对象的引用和指针
因为局部对象在函数调用完成后,他所占用的存储空间被释放,此时函数终止意味着局部变量的引用将指向不再有效的内存区域
const string& func()
{
string s;
s = "xiaodainiao"
return s; //错误,字符串字面值转换成一个局部临时变量,不能返回局部对象的引用
}
bool str\_cmp(const string &str1, const string &str2)
{
for (int i = 1; i < n; i ++)
{
if (str[1] != str[2])
return; //错误
}
return true; //这个往往会被忽略,在含有 return 语句的循环和条件后面也应该有一条 return 语句
}
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
l str_cmp(const string &str1, const string &str2)
{
for (int i = 1; i < n; i ++)
{
if (str[1] != str[2])
return; //错误
}
return true; //这个往往会被忽略,在含有 return 语句的循环和条件后面也应该有一条 return 语句
}
[外链图片转存中...(img-sf23ONq2-1714822011394)]
[外链图片转存中...(img-UechppkQ-1714822011394)]
[外链图片转存中...(img-OYZMv6mT-1714822011395)]
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**
**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618545628)**