关于函数传参问题(指针传参,值传参,引用传参)

 更新时间:2024年01月01日 10:35:04   作者:不是杠杠  
这篇文章主要介绍了关于函数传参问题(指针传参,值传参,引用传参),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

形参和实参

什么是形参(parameter),什么是实参(argument)

在函数定义中出现的参数可以看做是一个占位符,它没有数据,只能等到函数被调用时接收传递进来的数据,所以称为形式参数,简称形参

给形参传递值的变量称为实际参数,简称实参

形参和实参关系

1) 形参变量只有在函数被调用时才会分配内存,调用结束后,立刻释放内存,所以形参变量只有在函数内部有效,不能在函数外部使用。 

2) 实参可以是常量、变量、表达式、函数等,无论实参是何种类型的数据,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参,所以应该提前用赋值、输入等办法使实参获得确定值。 

3) 实参和形参在数量上、类型上、顺序上必须严格一致,否则会发生“类型不匹配”的错误。当然,如果能够进行自动类型转换,或者进行了强制类型转换,那么实参类型也可以不同于形参类型。

实参为值传值

代码:

#include<iostream>
using namespace std;
void swap(int a,int b)
{
    cout<<"a address1 = "<<&a<<endl;
    cout<<"b address1 = "<<&b<<endl;
    int temp = a;
    a = b;
    b = temp;
}
 
int main()
{
    int a = 10;
    int b = 20;
    cout<<"a address = "<<&a<<endl;
    cout<<"b address = "<<&b<<endl;
    cout<<"original "<<"a = "<<a<<" b="<<b<<endl;
    swap(a,b);
    cout<<"swaped "<<"a = "<<a<<" b="<<b<<endl;
    return 0;
}

执行结果:

分析结果:

实参a,b 和形参a,b的地址是不一样的,因为形参a,b是整型变量,他们在函数调用时分配内存,里面只是存放了和实参对应得整型值,所以改变形参变量a,b的值并没有改变实参a,b的值。形参a,b是临时变量,当函数运行结束时,他们的生命周期也就结束了。所以实参a,b的值并没有改变。

图解:

实参为指针传值

实参本身为普通变量

代码:

#include<iostream>
using namespace std;
void swap(int *a,int *b)
{
    cout<<"parameter a address1 = "<<&a<<endl;
    cout<<"parameter b address1 = "<<&b<<endl;
 
    cout<<"a value address1 = "<<a<<endl;
    cout<<"b value address1 = "<<b<<endl;
    int temp = *a;
    *a = *b;
    *b = temp;
}
 
int main()
{
    int a = 10;
    int b = 20;
    cout<<"a address = "<<&a<<endl;
    cout<<"b address = "<<&b<<endl;
    cout<<"original "<<"a = "<<a<<" b="<<b<<endl;
    swap(&a,&b);
    cout<<"swap "<<"a = "<<a<<" b="<<b<<endl;
    return 0;
}
 

执行结果:

分析结果:

*p 指的是 指针变量p所指向的地址所存放的内容

&p指的是指针本身的地址

p指的是指针所指向的内容的地址

实参传递的是实参a,b的地址,形参a,b为指针类型的变量,也就是对应存放的是实参a,b变量的地址,函数内交换形参a,b指针所指向地址的内容,也就是交换了实参a,b地址指向空间的内容,所以实参a,b的内容被交换。

图解:

 实参本身为指针

一级指针

代码:

#include<iostream>
using namespace std;
 
void newPoint(int *p)
{
    cout<<"parameter p address = "<<&p<<endl;
    p = new int;
    *p = 10;
}
 
 
int main()
{
    int *p = NULL;
    cout<<"argument p address = "<<&p<<endl;
    newPoint(p);
    cout<<"*p = "<<*p<<endl;
    delete p;
    return 0;
}
~           

执行结果:

分析结果:

实参指针p 没有指向任何类容为空,当实参给形参传递值时,传递的实际上是NULL,形参指针p 分配空间,仅仅只是给形参p分配了空间,当函数退出时,实参指针指向的内容还是为空,这时去访问实参p指向的内容,因为指针没有指向确切地址,就会产生段错误,同时因为函数new了空间没有释放,还会造成内存泄漏。

二级指针

代码:

#include<iostream>
using namespace std;
 
void newPoint(int **p)
{
    cout<<"parameter p address = "<<&p<<endl;
    *p = new int;
    cout<<"parameter p value = "<<p<<endl;
    cout<<"parameter *p value = "<<*p<<endl;
    **p = 10;
}
 
 
int main()
{
    int *p = NULL;
    cout<<"argument p address = "<<&p<<endl;
    newPoint(&p);
    cout<<"argument p value = "<<p<<endl;
    cout<<"*p = "<<*p<<endl;
    delete p;
    return 0;
}
~       

执行结果:

结果分析:

实参给形参传递的值是实参本身的地址 0x7ffe7feaa980,形参类型是二级指针,形参p存放的是一级指针实参p的地址,调用new之后,相当于是给实参指针p分配了空间,实参指针指向的地址为0x55d013b6d280,给**p赋值,相当于是给地址0x55d013b6d280指向的空间赋值,所以当函数返回时,实参指针指向了确定的地址0x55d013b6d280,并且地址0x55d013b6d280指向的空间值为10;

图解:

引用传值

代码:

#include<iostream>
using namespace std;
 
void swap(int& a,int& b)
{
    cout<<"parameter a address = "<< &a<<endl;
    cout<<"parameter b address = "<< &b<<endl;
    a = a+b;
    b = a-b;
    a = a-b;
 
}
 
int main()
{
    int a = 10;
    int b = 20;
 
    cout<<"argument a address = "<<&a<<endl;
    cout<<"argument b address = "<<&b<<endl;
    cout<<"original value"<<"a = "<<a<<" b ="<<b<<endl;
    swap(a,b);
    cout<<"swap value"<<"a = "<<a<<" b ="<<b<<endl;
    return 0;
}
~     

运行结果:

结果分析:

引用传值,函数形参并没有给形参分配内存,而是和实参相同的内存地址,节省了开销,建议能用引用传值的就用引用。

图解:

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • C语言中计算正弦的相关函数总结

    C语言中计算正弦的相关函数总结

    这篇文章主要介绍了C语言中计算正弦的相关函数总结,包括正弦和双曲线正弦以及反正弦的函数,需要的朋友可以参考下
    2015-08-08
  • C语言算法练习之佩奇借书

    C语言算法练习之佩奇借书

    这篇文章主要该大家分享C语言佩奇借书的练习,文章主要通过描述佩奇借书的问题然后确定程序框架将结果运算出来,下面来看详细内容吧,需要的朋友可以参考一下
    2022-03-03
  • C语言制作扫雷游戏(图形库)

    C语言制作扫雷游戏(图形库)

    这篇文章主要为大家详细介绍了C语言制作扫雷游戏,结合图形库,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-06-06
  • C语言数组任意位置插入一个元素方法

    C语言数组任意位置插入一个元素方法

    这篇文章主要给大家分享C语言数组任意位置插入一个元素方法,
    2021-11-11
  • C语言实现选择排序、直接插入排序、冒泡排序的示例

    C语言实现选择排序、直接插入排序、冒泡排序的示例

    这篇文章主要介绍了C++实现选择排序、直接插入排序、冒泡排序的代码示例,相当简洁直观,也是算法和数据结构学习中的基础,需要的朋友可以参考下
    2016-02-02
  • C语言创建链表错误之通过指针参数申请动态内存实例分析

    C语言创建链表错误之通过指针参数申请动态内存实例分析

    这篇文章主要介绍了C语言创建链表错误之通过指针参数申请动态内存,是链表创建过程中非常常见的经典错误。实例中做了较为详尽的分析,需要的朋友可以参考下
    2014-09-09
  • C++分析类的对象作类成员调用构造与析构函数及静态成员

    C++分析类的对象作类成员调用构造与析构函数及静态成员

    终于到了对象的初始化和清理的最后阶段了,在这里分享一个cpp里有多个类时,一个类的对象作为另一个类成员的时候构造函数和析构函数调用的时机。还有一个静态成员也是经常考到的点,在这篇博客将会详解其概念并举出案例巩固,让我们开始
    2022-05-05
  • C++详细讲解内存管理工具primitives

    C++详细讲解内存管理工具primitives

    文章向大家介绍C++内存管理primitives,主要包括primitives使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下
    2022-06-06
  • C++控制台实现贪吃蛇游戏

    C++控制台实现贪吃蛇游戏

    这篇文章主要为大家详细介绍了C++控制台实现贪吃蛇,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-04-04
  • C++使用htslib库读入和写出bam文件的实例

    C++使用htslib库读入和写出bam文件的实例

    下面小编就为大家分享一篇C++使用htslib库读入和写出bam文件的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2017-11-11

最新评论