C++ 参数传递
每次调用函数都会重新创建他的形参,并用传入的实参对形参进行初始化。
当形参是引用类型时,我们说他对应的实参被引用传递,或者函数被传引用调用,和其他引用一样,引用形参也是他绑定的对象的别名。
当实参的值被拷贝给形参时,实参和形参是两个相互独立的对象,我们说这样的实参被值传递或者函数被传值调用。
传值参数

尽管函数改变了val的值,但是这个改动不会影响到实参的值(图中的cnt)。
指针形参
当执行指针拷贝操作时,拷贝的是指针的值,拷贝之后两个指针是不同的指针,因为指针使我们可以间接访问他所指的对象,所以通过指针可以修改他所指对象的值。


C++中建议使用引用类型的形参代替指针,如图二。
传引用参数
通过引用形参,允许函数改变一个或多个实参的值。

reset函数中,i其实就是a的另一个名字,所以对i的操作就是对a的操作。
使用引用避免拷贝
拷贝大的类对象或容器对象比较低效,甚至有的类不支持拷贝,所以只能通过引用参数访问该类对象。

我们如果要比较两个很长的string对象,我们就要避免拷贝他们,应该使用引用形参,又因为不需要改变string的内容,把形参定义为常量的引用。
注意:如果函数无需改变引用形参的值,最好将其声明为常量引用。
使用引用形参返回额外信息
如果我们想一个函数返回多个参数,可以使用引用形参。
如果我们想记录一个string某个字符第一次出现的位置并且直到他出现了多少次。

const形参和实参
这里我们复习一下

用实参初始化形参的时候形参会忽略顶层const,当形参有顶层const时,传给他常量对象或者非常量对象都是可以的。

fcn可以读取i的值,但是不能向i写值,同时调用fcn时,既可以传int也可以传const int。

因为顶层const被忽略掉,所以上面两个fcn传入的参数可以完全一样,因此第二个fcn是错误的。
指针或引用形参与const
形参的初始化方式和变量初始化是一样的,我们可以使用非常量初始化一个底层const,凡是反过来不行。
要想调用引用版本的reset,只能使用int类型对象,而不能使用字面值,求值结果为int表达式、需要转换的对象或者const int类型对象。要想调用指针版本的reset只能用int*。
如果函数的参数是常量引用,那么允许我们用字面值去初始化。
尽量使用常量引用
把函数不会改变的形参定义成普通引用会带给调用者一种误导,即函数可以修改他的实参的值。此外使用引用而非常量引用也会极大的限制函数所能接受的参数类型。就像我们刚才说的,我们不能把const对象、字面值或者需要类型转换的对象传递给普通引用形参。

还有一种难以觉察的错误

如果其他函数中定义了常量引用,那么这个参数在非常量定义的find_char中无法使用。
你有几种办法可以解决该问题。
1修改is_sentence的参数类型,这样他们都不能接受字面值
2修改find_char的参数类型
3在is_sentence中定义一个副本,把这个副本传给find_char
数组形参
我们不能拷贝数组,所以无法以值传递的方式使用数组参数,因为数组会被转换为指针,所以当我们用函数传递一个数组时,实际上传递的时数组的首元素的指针。

这三个函数时等价的,当编译器处理print函数时,只检查传入的参数是否时const int*类型。

因为数组是以指针的形式传递给函数的,所以函数一开始并不知道数组的确切尺寸,管理指针形参有三种常用技术。
使用标记指定数组长度

这种方法要求数组本身包含一个结束标记,对于想int那样所有取值都合法的数据就不太有效了。
使用标准库规范

这种方法是传递指向数组首尾元素的指针。只要调用者能正确计算指针所指的位置,上述方法就是正确的。
显式传递一个数组大小的形参

只要size的值不超过数组实际大小,函数就是安全的。
数组形参和const
我们对引用的讨论同样适用于指针(也就是数组首元素的指针),只有当确定需要改写元素值的时候我们才定义非常量指针。
数组引用形参
我们可以定义数组的引用,所以形参也可以是数组的引用。

这一用法无形中限制了print的使用,因为只能作用于大小为10的数组,我们以后会详细介绍如何给引用类型的形参传递任意大小的数组。
面对多维数组,其实也就是数组的数组,我们传递的也是数组首元素的指针,数组第二维的大小都是数组类型的一部分,不可忽略。

这两种是等价定义,此时编译器会忽略掉第一个维度,所以最好不要把他包括在形参列表内,matrix看似是一个二维数组,实际上是指向含有10个数组的指针。

注意:括号必不可少!