C++的参数传递机制 C++一共有三种传递方式:值传递(pass by value)、指针传递(pass by pointer)、引用传递(pass by reference)。 关键点:在函数中,编译器总是要为函数的每个参数制作临时副本。引用传递除外。 一.值传递。 值传递很简单。唯一要注意的就是当值传递的输入参数是用户自定义类型时,最好用引用传递代替,并加上const关键字。因为引用传递省去了临时对象的构造和析构(见关键点)。 数据类型为内部类型时,不必。 例如: 将void Func(A a) 改为void Func(const A &a); 而void Func(int a)就没必要改成void Func(const int &a)。 二.指针传递。 今天之所以会花时间参阅C++的参数传递机制,就是因为对指针传递这一部分的应用出了问题。 例如: 在下面的getMemory函数中获得动态内存分配的指针p,并未能将获得的内存返回。 void getMemory(char *p, int num) { p = new char[num]; } void Test(void) { char *str = NULL; getMemory(str, 100); // str 仍然为 NULL strcpy(str, "hello"); // 运行出错 delete [] p; } 出错的原因就是在于上面提到的关键点。 编译器总是要为函数的每个参数制作临时副本,指针参数p的副本是 _p,编译器使 _p = p。如果函数体内的程序修改了_p的内容,就导致参数p的内容作相应的修改。这就是指针可以用作输出参数的原因。 而在上例中, 副本_p申请了新的内存,只是把 _p所指的内存地址改变了,但是p丝毫未变。所以函数getMemory并不能输出任何东西。并且,每执行一次getMemory就会泄露一块内存,因为没有用free释放内存。 解决方法有三种: 甲)利用全局变量。 定义一个全局变量str,这样就不用把它作为参数来传递,也就不会有副本 _str。 char *str = NULL; void getMemory(int num) { str = new char[num]; } 乙)用“指向指针的指针”。 void getMemory(char **p, int num) { *p = new char[num]; } void Test(void) { char *str = NULL; getMemory(&str, 100); // 注意参数是 &str,而不是str strcpy(str, "hello"); cout<< str << endl; delete [] str; } 丙)返回指针变量 char *getMemory(int num) { char *p = new char[num]; return p; } void Test(void) { char *str = NULL; str = getMemory(100); strcpy(str, "hello"); cout<< str << endl; delete [] str; } 三.引用传递。 引用传递时,对形参的操作等同于对实参的操作,即传递的不会是实参的副本,而就是实参。
C++区别于C的一个新增优势。虽然用&作为标识符,但是跟指针一点关系都没有。 int &a=b表示,a和b是同一个变量。简单地说,相当于一个别名,如:Stephen Chow和周星驰。 当作为参数传递时,它省去了临时对象的构造和析构。 用法如下: Func(int &a) { a++; } void Test(void) { int i; Func(i); } |
|