函数参数的值传递与引用传递、指针传递的区别
需要预先了解:
1. 形参与实参
1.1 形式参数(Parameter)
形参是函数定义或函数声明时,在参数列表中声明的变量,是函数内部用来接收外部数据的占位符。
- 函数未被调用时,不占用实际内存
- 函数被调用时,创建并初始化
- 函数执行结束后立即销毁
1.2 实际参数(Argument)
实参是调用函数时传递给函数的具体数据。
// a、b是形参
int add(int a, int b)
{
return a + b;
}
int main()
{
int x = 10, y = 20;
// x+y、x*y是实参
int res = add(x + y, x * y);
return 0;
}
2. 值传递
形参是实参的一份独立拷贝,形参与实参占有不同的内存地址。
- 函数内对形参的修改都不会作用于外部的实参
- 如果参数的内存占用过大,频繁地拷贝会导致明显的性能问题
void swap(int x, int y)
{
int temp = x;
x = y;
y = x;
}
int main()
{
int a = 10, b = 20;
swap(a, b);
std::cout << "a: "<< a << ",b: " << b << std::endl;
}
3. 指针传递与引用传递
指针传递中,形参是一个指针变量,实参是地址值,因此可以正确修改外部空间,形参仅对大小4字节或8字节的地址值进行拷贝。
swap(int* x, int* y)
{
int temp = *x;
*x = *y;
*y = temp;
}
swap(&a, &b);
引用传递中,形参是实参的引用,形参与实参指向同一块内存空间,可以通过修改形参来直接修改外部的实参,拷贝花销与指针相同。
swap(int& x, int& y)
{
int temp = x;
x = y;
y = temp;
}
swap(a, b);
4. 结论
4.1 特征总结
- 指针传递与引用传递需要传输8字节的地址值,值传递需要传输实参的全部数据
- 指针传递和引用传递可以实现对实参的修改,值传递不可以
4.2 传参选择
- 如果需要修改实参的值,必须选择指针传递或引用传递
- 如果不需要修改实参的值,按照以下原则选择:
- 如果实参数据量较小(内置数据类型int、float等,或是很小的结构体),选择值传递
- 如果实参数据量较大(大型结构体、类对象等),选择指针传递或引用传递;此时可以用
const修饰参数,防止在函数内部修改实参的值:
void print(const char* str)
{
std::cout << str << std::endl;
}
void print(const std::string& str)
{
std::cout << str << std::endl;
}


