12. 参数传递
当形参是引用类型时,称对应实参被 引用传递 (passed by reference)或者函数被 传引用调用 (called by reference)。
当实参的值被 拷贝 给形参时,形参和实参时两个相互独立的对象。这样的实参被 值传递 (passed by value)或者函数被 传值调用 (called by value)。
12.1. 传值参数
当初始化一个非引用类型的变量时,初始化被拷贝给变量。此时,对变量的改动 不会 影响初始值。
- 指针形参
指针的行为和其他 非引用 类型一样。当执行指针拷贝操作时,拷贝的是指针的值。拷贝之后, 两个指针是不同的指针 。因为指针 使我们可以间接地访问它所指的对象,所以通过指针 可以修改它所指的对象的值 。
1void reset(int* p)
2{
3 *p = 0; // 改变了指针p所指对象的值
4 p = 0; // 只改变了p的局部拷贝,实参未被改变
5}
6
7templtate<class T>
8void swap(T* x, T* y)
9{
10 T* tmp = x;
11 x = y;
12 y = tmp;
13}
14// 只交换了拷贝指针的值,实际指针并未改变,因此无法达到交换的目的。
为了改变实参指针的值,可以使用指针的引用或者使用指向指针的指针。
int val = 1;
int* p = &val;
// 调用: reset(p)
void reset(int* &p)
{
*p = 0; // 改变了指针p所指对象的值
p = 0; // 改变了指针p的值
}
// 调用: reset(&p)
void reset(int** p)
{
**p = 0; // 改变了指针*p所指对象的值
*p = 0; // 改变了指针*p的值
}
12.2. 传引用参数
通过使用引用形参,允许函数改变实参的值。
使用引用避免拷贝:拷贝大的类类型对象或者容器对象比较低效,甚至有的类类型(比如IO类型)根本不支持拷贝操作。当某种类型不支持拷贝操作时,函数只能通过 引用形参访问该类型的对象。例如,需要比较两个string对象,而这样的对象可能会很长,为了避免拷贝且不改变对象的值,可以将形参声明为常量引用(const &)。
使用引用形参返回额外信息:通过给函数传入一个额外的引用形参,让其保存需要的值,而不需要作为函数返回值返回(避免函数返回值太多)。
12.3. 删除指针
如果实参是一个动态申请的指针(new),在函数内 delete 该指针需要慎重。下例基于 Visual Studio 2013。
值传递:删除之后实参指针本身的值不变,指向的值仍然可以访问,但结果是未知的。
1void delPtr(int* p) 2{ 3 delete p; 4} 5 6int main() 7{ 8 int* p = new int(6); 9 cout << p << ends << *p << endl; // 00746AE0 6 10 delPtr(p); 11 cout << p << ends << *p << endl; // 00746AE0 -572662307 12 return 0; 13}
引用传递:删除之后实参指针本身改变,指向的值不能访问(报错),说明空间得到释放。
1void delPtr(int* &p) 2{ 3 delete p; 4} 5 6int main() 7{ 8 int* p = new int(6); 9 cout << p << ends << *p << endl; // 006F6AE0 6 10 delPtr(p); 11 cout << p << endl; // 00008123 12 cout << *p << endl; // runtime error 13 return 0; 14}
12.4. 参考资料
《C++ Primer 第5版 中文版》 Page 187 – 190。