一、函数参数传递方式-概述
C++的函数参数传递方式,可以是传值方式,也可以是传引用方式。
- 传值的本质是:形参是实参的一份复制。
- 传引用的本质是:形参和实参是同一个东西。
传值 和 传引用,对大多数常见类型都是适用的。
如果希望通过将参数传递到函数中,从而来改变变量的值(比如变量是T a,T表示类型),则可以有这2种方式选择:
- 传 a 的引用:
void my_fun(T &a)
; - 传 a的地址:
void my_fun(T *a)
;
1、普通类型
- 传值(复制产生新的变量)
void fun_1(int a); int类型,传值(复制产生新的变量)
- 传引用(形参和实参是同一个东西)
void fun_2(int &a); int类型,传引用(形参和实参是同一个东西)
2、指针、数组
指针、数组,它们都是数据类型的一种,没啥特殊的,因此指针作为函数参数传递时,也区分为传值和传引用两种方式。
- 指针类型,传值(复制产生新的变量)
void fun_3(int* p); 指针类型,传值(复制产生新的变量)
- 指针类型,传引用(形参和实参是同一个东西)
void fun_4(int* &p); 指针类型,传引用(形参和实参是同一个东西)
二、函数参数传递方式-对比
1、传值
这种传递方式中,实参和形参是两个不同的地址空间,参数传递的实质是将原函数中变量的值,复制到被调用函数形参所在的存储空间中,这个形参的地址空间在函数执行完毕后,会被回收掉。整个被调用函数对形参的操作,只影响形参对应的地址空间,不影响原函数中变量的值,因为这两个不是同一个存储空间。
即使形参的值在函数中发生了变化,实参的值也完全不会受到影响,仍为调用前的值。
2、传地址
这种传递方式中,实参是变量的地址,形参是指针类型的变量,在函数中对指针变量的操作,就是对实参(变量地址)所对应的变量的操作,函数调用结束后,原函数中的变量的值将会发生改变。
被调用函数中对形参指针所指向的地址中内容的任何改变都会影响到实参。
3、传引用
这种传递方式中,形参是引用类型变量,其实就是实参的一个别名,在被调用函数中,对引用变量的所有操作等价于对实参的操作。这样,整个函数执行完毕后,原先的实参的值将会发生改变。
被调函数对形参做的任何操作都影响了主调函数中的实参变量。
使用引用类型就不必在swap中声明形参是指针变量,指针变量要另外开辟内存单元,其内容是地址。
而引用变量不是一个独立的变量,不单独占内存单元。而且在调用swap函数时,只需要传值即可,将引用作为函数的形参更加简单、直观、方便。
void swap(int &a, int &b)
{
int temp = a;
a = b;
b = temp;
}
4、哪种更高效?
在内置类型当中三种传递方式的效率上都差不多;
在自定义类型当中,传引用方式效率的更高效一些,因为它没有对形参进行一次拷贝
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
//值传递
void mySwap(int a, int b)
{
int tmp = a;
a = b;
b = tmp;
cout << "mySwap::a = " << a << endl;
cout << "mySwap::b = " << b << endl;
}
void test01()
{
int a = 10;
int b = 20;
mySwap(a, b);
cout << "a = " << a << endl;
cout << "b = " << b << endl;
}
//地址传递
void mySwap2(int * a, int * b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
void test02()
{
int a = 10;
int b = 20;
mySwap2(&a, &b);
cout << "a = " << a << endl;
cout << "b = " << b << endl