一、函数传递参数的方式
术语:
主调函数:调用其他函数的函数,大部分时候为main函数
被调函数:被其他函数如main函数调用的函数
变元:在主调函数中传递给被调函数的变量或常量,如函数调用语句function(a,b)中变元为a和b
形式参数:主调函数传递给被调函数的变量或常量
1.按值传送机制
此类函数传送机制是将主调函数中的变元生成一个副本作为被调函数的形式参数,即将变元重新拷贝一份然后再传递给被调函数。显然,在这种传递机制下,在被调函数中对形式参数的操作并不会影响主调函数内的变量。
1.1传递普通变量
这里的普通变量是指基本类型变量,如 Int , double 等,当这些变量作为变元传递给被调函数后,被调函数可对这些变量进行操作,但不会影响主调函数内的变元。
1.2传递指针变量(指针还没整明白的同学戳这里(指针专题))
首先应明确,指针变量的值是一个对应类型变量的地址,所以传递指针仍是按值传递。当我们将指针作为变元传递给被调函数时,程序依然会生成一个指针变量副本并作为形式参数传递给被调函数,因此形式参数指针存储的地址与原指针一模一样,即两个指针指向内存中同一块区域。因此,当我们在被调函数中对形式参数指针进行解引用赋值等操作时,对应内存区域上的值也会被改变。
1.3传递数组
当传递整个数组时,我们一般会选择将数组名传递给被调函数以节省时间开销。数组名本身是一个常量指针,指向内存中一块连续的存储数组元素的空间。当数组名作为变元时,数组名被复制后传递给被调函数,此时被调函数中的指针也指向同一块连续的内存空间,因此,我们也可以通过形式参数指针对这块内存进行操作。
1.4传递const 指针参数
通过1.2和1.3我们发现,每次传递指针后,被调函数都能直接通过形式参数指针来对原指针指向的内存空间进行修改,而有时我们并不希望被调函数修改它们。所以,当我们只需要访问元素而并不需要修改它们时,我们可以在形式参数指针前加上一个 const 关键词,如:
void function(const int* p) {
*p = 3;//无法编译,因为此时p是常量,无法作为表达式左值
std::cout << *p;//可以访问
}
int main()
{
int a{
10 };
int *pa{
&a };
function(pa);
}
值得注意的一点是,非const变元可以传递给const形式参数和非const形式参数,但const变元只能传递给const形式参数。
2.按引用传送机制
什么是引用
引用是一个变量的别名,也可以说,引用等价于原变量。一个引用必须满足以下两个条件:1.引用不可为空,一定要初始化。2.一旦初始化后,引用不可改变其指向。要使用左值引用类型,只需在类型名后面加上&,如:
int variable{
3 };
int &cite = variable;
cite++;
std::cout << variable;//结果为4
此时 cite 是 variable 的引用,对 cite 的操作完全等价于对 variable 的操作。
按引用传递参数
当被调函数的形式参数为引用时,同样的,它就是主调函数中变元的别名。此时,在传递过程中,程序不会生成变元副本,而是直接将变元本身传递过去。因此在被调函数中对引用参数的操作会直接影响主调函数中的变元。主调函数中变元地址与引用参数地址是相同的。
void function(int &cite) {
cite++;
std::cout << &cite << std::endl;//引用参数cite的地址
}
int main()//从main函数开始阅读程序是一个良好的习惯
{
int variable{
3 };
function(variable);
std::cout << variable << std::endl;//结果为4,其值已经在function中加1
std::cout << &variable << std::endl;//主调函数中变元地址
}
在