前言:
如今兄弟们对“c语言中的引用传递”大概比较关心,姐妹们都需要知道一些“c语言中的引用传递”的相关资讯。那么小编也在网摘上汇集了一些对于“c语言中的引用传递””的相关内容,希望各位老铁们能喜欢,你们快快来学习一下吧!一、开篇
在C++中,函数参数的传递有六种不同的情况:
(1)传值参数
(2)指针形参
(3)传引用参数
(4)数组形参
(5)可变形参函数
(6)省略符形参
在实际C++使用中,前四种是经常使用到的参数传递方式,后两种可能使用频次不多,但是在阅读其他项目源码时可能会遇见!
二、参数传递基础知识函数的参数传递有两个概念:【形参和实参的参数传递】 、【 函数调用过程】。每次函数调用,都会重新创建函数的形参,并使用传入的实参对形参进行初始化(形参初始化的机理与变量初始化一样)。重磅一句话:函数形参的类型决定了形参与实参的交互方式。如果形参的类型是引用类型,那么它将绑定到对应的实参上;否则,会将实参的值拷贝后赋值给形参。
总结一下:
1、函数调用需要开销。
2、函数形参的类型决定了函数调用时,形参与实参的交互方式:拷贝赋值or引用绑定。
注:站在函数参数传递方式的角度考虑:拷贝赋值又叫做值传递;引用绑定又叫做引用传递。
三、传值参数
当初始化一个非引用类型的变量时,初始值会被拷贝给变量。对变量的改动不会影响初始值,因为此刻存在两份值对象。所以,在函数中对形参所做的所有改动操作都不会影响实参。
四、指针形参
函数调用时,指针的行为与其他非引用类型一样。在执行指针拷贝操作时,拷贝的是指针的值,拷贝后,两个指针是不同的指针。但是,指针允许间接的访问到它所指的对象,所以通过指针可以修改它所指对象的值。
在C语言中,常常使用指针类型的形参访问函数外部的对象。在C++语言中,建议使用引用类型的形参替代指针。
五、传引用参数(5-1)使用引用避免拷贝
拷贝大的类类型对象或者容器对象是比较低效的操作,甚至有些类类型(包括IO类型在内)根本就不支持拷贝操作,此时把此类类型作为函数的参数传递,将会引发错误。因此,当某种类型不支持拷贝操作时,函数只能通过引用形参访问该类型的对象。
如果在函数中不会改变引用形参的值,最好将其声明为常量引用,这么做是一种比较规范的代码设计。
(5-2)使用引用形参返回额外的参数信息
通常, 一个函数只能返回一个值,但是有时候我们的函数需要同时返回多个值,此时则可以使用引用来返回多个结果。
通过函数引用形参返回多个参数。如下代码示例:
#include <iostream>class student{public: void getStudentInfo(std::string &name,int &age) { name = m_name; age = m_age; } private: std::string m_name = "zhangSan"; int m_age = 25;};int main() { student stu_1; std::string stu1_name; int stu1_age; stu_1.getStudentInfo(stu1_name,stu1_age); std::cout<<"student1_name:"<<stu1_name<<std::endl; std::cout<<"student1_age:"<<stu1_age<<std::endl; return 0;}六、数组形参
数组作为函数的参数传递时,有两个重要特性:
(1)不允许拷贝数组。
(2)使用数组时,编译器通常会将其转换为指针
不能以值传递的方式传递数组,但是函数形参可以写成类似于数组的形式,如下代码:
void print_info(const int *);void print_info(const int[]);void print_info(const int[10]); //数组的大小对函数调用没有影响
因为传递数组是以指针的方式传递,所以我们在函数中是不知道数组的大小,因此需要函数调用者传递额外的数组大小信息。计算数组的大小有三种方式:
(1)使用标记指定数组长度。
这种方式,必须要求数组有一个结束标记,这种对于字符串非常有用,但是对于全是int类型的数组无效。例如以下代码:
void print_array(char *cp){ if(cp) { while(*cp) { std::cout<<*cp++; } }}
(2)使用标准库+数组开始位置和结束位置计算数组大小
例如以下代码:
voit print_array(int *start, int *end){ while(start != end) { std::cout<< *start++ <<std::endl; }}
对于以上代码,在调用print_array()函数的时候,需要传入一个数组的首元素的指针和一个指向数组尾后元素的指针。
int main(){ int num[5] = {1,4,3,2,5}; //调用标准库函数begin和end作为print_array()的实参。 print_array(begin(num), end(num));}
end()函数用于返回一个数组尾元素的下一个位置。
(3)显式传递一个表示数组大小的参数
例如以下代码:
void print_array(const int ar[],size_t size){ for(size_t i = 0; i < size ; ++i) { std::cout << ar[i] << std::endl; }}
在函数中使用数组时必须保证对数组的操作不会越界。
七、可变形参函数
在实际开发中,有时我们不能提前预测传递给函数的实参个数,且我们希望把这一系列的操作归一到一个函数中,在C++11标准中,提供了两种方法实现这种可变形参个数的实现方法:
(7-1)initializer_lit形参
#include <iostream>using namespace std;void print_error_msg(initializer_list<string> error_info){ for(auto begin = error_info.begin();begin != error_info.end(); begin++) { cout<< *begin <<endl; } cout<< "----------------"<<endl;}int main() { int param_num = 3; do{ if(param_num == 3) { print_error_msg({"03","error","information"}); } else if(param_num == 2) { print_error_msg({"02","error"}); } else if(param_num == 1) { print_error_msg({"01"}); } }while ((param_num--) > 0); return 0;}
结果如下:
<font color = "red">initializer_list的使用条件和注意事项:
(1)函数中全部实参的类型完全相同!</font>
(2)initializer_list对象中元素永远是常量值,无法改变initializer_list对象中元素的值。
(7-2)省略符形参
省略符形参是为了给C++程序访问特殊的C代码而设置的,这些代码会使用到C标准库中varargs功能。
例如下列代码:
#include <stdio.h>#include <stdargs.h>int sum_ops(int num, ...) { va_list valist; int ret = 0; va_start(valist, num); for (int i = 0; i < num; i++) { ret += va_arg(valist, int); } va_end(valist); return ret;}int main() { printf("2+3 = %d\n", sum(2, 2, 3)); printf("1+2+3+4 = %d\n", sum(4, 1, 2, 3, 4));}
省略符形参只能出现在形参列表的最后一个位置,形式有两种:
//这种形式指定了ops函数的部分参数的类型,对应于这些形参的实参将会执行正常的类型检查,//省略符形参所对应的实参无须类型检查。(1)void ops(param1,param2,...);//形参声明后面的逗号是可选的。(2)void ops(...);
省略符形参应该仅仅用于C和C++通用的类型。需要注意的是:大多数类类型的对象在传递给省略符形参时都无法正确拷贝!!!因此,不能将类类型以省略符形参的方式进行传递。
标签: #c语言中的引用传递 #c语言的函数都是外部函数 #c语言中函数形参类型 #c语言参数引用 #c语言参数传递的两种方式有哪些