1 值传递
调用子函数时把主函数中实参的值传递给子函数的形参,在子函数中完成对应的操作。此时,子函数中的所有操作都是对形参来进行的,因此主函数中的实参不受子函数的影响。
且子函数的形参存放在栈区,函数调用完成后由编译器自动释放!
以交换两个数为例:
(1) 子函数
// 值传递
void swapab_value_transmit(int a, int b)
{
int temp = a;
a = b;
b = temp;
}
(2)主函数
void main()
{
int a = 10;
int b = 20;
// 值传递( 不改变实参的值 )
swapab_value_transmit(a, b);
cout << "值传递:" << "a=" << a << " b=" << b << endl;
}
效果:
显然,由于是值传递,子函数并没有完成主函数中参数值的交换!
2 地址传递
调用子函数时把主函数中实参的地址传递给子函数的形参(此时子函数的形参用指针来接收实参的地址)。因此,此时子函数是直接对实参的地址所指向的内存空间进行操作的,故可以改变的实参的值!
即使子函数调用结束后形参被释放,但由于形参指针指向主函数实参的地址,故在对形参进行操作时也同时对实参进行了相同的操作。
以交换两个数为例:
(1) 子函数
// 地址传递
void swapab_addr_transmit(int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
(2) 主函数
void main()
{
int a = 10;
int b = 20;
// 地址传递( 直接对地址进行操作,可改变实参的值 )
swapab_addr_transmit(&a, &b);
cout << "地址传递:" << "a=" << a << " b=" << b << endl;
}
效果:
显然,由于是地址传递,子函数完成了主函数中实参值的交换!
3 引用传递
- 引用的作用: 给变量取别名
- 引用的语法:数据类型 &别名 = 原名 (数据类型要与原变量一致)
- 引用的注意事项:必须初始化、初始化后不可更改(不能再做其他变量的别名)
- 引用作为函数参数优势:可以达到与地址传递相同的效果且简化代码和语法!
当引用作为函数参数时, 调用子函数时把主函数中实参名称(原名)所指向的内存取一个别名(子函数的形参),即别名和原名都指向同一段内存空间。因此,在子函数中对形参操作是直接对实参的内存进行操作,从达到了在子函数中操作实参的效果!且该写法简化代码书写!
以交换两个数为例:
(1) 子函数
// 引用传递
// 引用给变量起别名,通过原名和别名都可访问变量的地址
void swapab_cite_transmit(int& a, int& b)
{
int temp = a;
a = b;
b = temp;
}
(2) 主函数
void main()
{
int a = 10;
int b = 20;
// 效果与地址传递相同(直接对实参的地址进行操作),可改变实参的值
swapab_cite_transmit(a, b);
cout << "引用传递:" << "a=" << a << " b=" << b << endl;
}
效果:
显然,由于是引用传递,子函数完成了主函数中实参值的交换!
4 const在函数形参中的应用
const 关键字可以定义常量,const修饰的常量在程序中不能被修改,用const定义常量的基本语法为:
const type variable = value;
在函数形参列表中使用const的主要作用为:const 修饰的变量可以把对应的变量改为只读状态,避免对原数据进行误操作!
4.1 值传递形参的应用
作用:防止对传入变量的误操作!
(1) 子函数
void test(const int a)
{
// a = a + 1; //会报错,const修饰的变量不能被修改
cout << "a=" << a << endl;
}
(2)主函数
void main()
{
int a = 10;
test(a);
}
4.2 地址传递形参中的应用
const修饰指针变量的方式主要有:
- 常量指针: const type * p (指针p的指向可以修改,指针p的指向的值不能修改)
- 指针常量: type * const p (指针p的指向不可修改,指针p的指向的值可以修改)
- 即修饰指针又修饰常量:const type * const p (指针p的指向和指向的值都不可修改)
函数示例:
void test1(const int * a) // 常量指针,指向的值不能修改
{
// *a = 2; //会报错,指向的值不能修改
int b = 20;
a = &b; //正确,指针的指向可以修改
cout << "a=" << *a << endl;
}
void test2( int* const a) // 指针常量,指针指向不能修改
{
int b = 20;
//a = &b; // 错误,指针指向不能修改
*a = 20; // 正确,指针的指向的值可以修改
cout << "子函数 a= " << *a << endl;
}
void test2( const int* const a) // 指针常量,指针指向不能修改
{
int b = 20;
// a = &b; // 错误,指针指向不能修改
//*a = 20; // 错误,指针的指向的值不能修改
cout << "子函数 a= " << *a << endl;
}
4.3 引用传递形参中的应用
常量引用语法(允许直接赋予数值):
// 1.可直接赋予数值
const int & name = 10;
// 编译器自动优化为: int temp= 10; const const int & name = temp;
// 2.也可赋予变量名
int a = 20;
const int & name = a;
作用:主要用于修饰形参防止误操作!
void test(const int & a)
{
//a = 20; // 错误, const修饰的引用不可修改
cout << "子函数 a= " << a << endl;
}
因此,常量引用作为函数参数时有两种调用方式:
void main()
{
int a = 10;
test(a); // 给变量名
test(20); // 直接给数值
}
效果: