龙空技术网

C++函数参数传递,都了解吗?

嵌入式小生 141

前言:

如今兄弟们对“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语言参数传递的两种方式有哪些