前面我们介绍了函数的调用约定,明白了函数调用者与被调用者之间传递参数的顺序与如何进行栈恢复的。 实际上,函数调用者如何将参数传递给被调用者也是有讲究的。 总的来说,函数参数传递分为3种情况:传值,传指针和传引用。

首先,理解一下实参与形参的概念。
int func(int x)//x是形参
{
    return x*x;
}
int main(void)
{
    int a = 10;
    func(a);//a是实参
    return 0;

上面的代码中,x是形参,a是实参。形参x是实参a的一个拷贝。

一,传值

所谓传值,顾名思义,就是把实参的值直接传递给函数。因为形参是实参的拷贝,所以传值无法改变实参。在C++里面,如果传递的是对象, 那么,在传值过程中,还会隐式的调用对象的拷贝构造函数,有一定的计算执行开销(相当于创建了一个临时对象,函数调用完成后执行临时对象的析构函数)。
void func(int x)//func采用了传值的形式
{
    x = x+1;
    printf("x=%d\n", x);
}
int main(void)
{
    int a = 0;
    func(a);//传值不能修改a的值
    printf("a=%d\n", a);
    return 0;
}
分析:上面的程序采用了传值的参数传递形式,把a的值0传递给了func函数,而由于x是a的一个拷贝,因此,x=x+1值修改了x的值 并没有修改a的值。所以上面程序执行的结果,输出为:
x=1
a=0

二,传指针

传指针就是把实参的地址传递给函数。传指针可以修改实参的值,在C++里也不会存在调用对象的拷贝构造函数的问题, 传指针的效率比传值要高。所以,如果需要修改实参的值,就不能传值,而需要传指针等。
但是,传指针比传值复杂,指针计算一旦移动出了正常范围,会造成程序的非法访问等。
void func(int *x)//func采用了传指针的形式
{
    *x = *x+1;
    printf("*x=%d\n", *x);
}
int main(void)
{
    int a = 0;
    func(&a);//把实参a的地址传递给了函数func
    printf("a=%d\n", a);
    return 0;
}
分析:传指针可以修改实参的值。根据指针的定义,*x就是a,所以,*x=*x+1,即为a = a+1,所以上面的代码输出结果为:
*x=1
a=1

三,传引用

所谓引用其实就是变量的一个别名。传引用是C++里面引入的一种参数传递方法。传引用实际上也是传递的实参的指针,所以能够修改实参的值。 但是,引用的特性告诉我们,一旦引用初始化后,这个引用就不能再改变。所以,传递引用实际上是拥有传值的方便简单,也同时 具备了传指针的高效,又没传指针的危险,相对安全。

void func(int &x)//func采用了传引用的形式
{
    x = x+1;
    printf("x=%d\n", x);
}
int main(void)
{
    int a = 0;
    func(a);//把实参a的引用传递给了函数func
    printf("a=%d\n", a);
    return 0;
}
分析:func采用传引用的方法定义,实参a引用传递给函数func之后,func能够修改实参的值。所以上面的程序执行结果为:
x=1
a=1
总之:传值不能修改实参,且如果是对象,效率较低;传指针能够修改实参,效率较高,但容易出错;传引用能够修改实参,效率较高,而且不易出错。

C/C++ 函数参数传递:传值,传指针,传引用的更多相关文章

  1. C++函数的传值调用&指针调用&引用调用

    目录 传值调用 指针调用 引用调用 传值调用 该方法把参数的实际值复制给函数的形式参数.在这种情况下,修改函数内的形式参数对实际参数没有影响. #include<iostream> usi ...

  2. Python学习笔记之函数参数传递 传值还是传引用

      在学完Python函数那一章节时,很自然的的就会想到Python中函数传参时传值呢?还是传引用?或者都不是? 在回答上面的问题之前我们先来看看下面的代码: 代码1: def foo(var): v ...

  3. virtual 函数只有在用指针或引用的方式访问,才会导致多态。

    只有用指针和引用,才会动态绑定.才会在运行时候从虚表中找对应的成员函数. 如果只是用.访问成员函数,是静态绑定,在编译时刻就固定好的. 另外,父类的虚函数,子类不管加不加virtual关键字,都是虚函 ...

  4. C++中指针和引用、数组之间的区别

    指针指向一块内存,它的内容是所指内存的地址:而引用则是某块内存的别名,引用初始化后不能改变指向.使用时,引用更加安全,指针更加灵活. 初始化.引用必须初始化,且初始化之后不能呢改变:指针可以不必初始化 ...

  5. C#-函数的传值与传址

    传值就是将实参的值传到所调用的函数里面,实参的值并没有发生变化,默认传值的有int型,浮点型,bool型,char字符型,结构体等等. 传址就是将地址传到所调用的函数里面操作,实参的值也会跟着变化,传 ...

  6. [ 随手记6 ] C/C++ 形参、实参、按值传参、指针传参、引用传参

    个人原创: 1. 形参:形式上的参数,一般多在函数声明.函数定义的参数上: 2. 实参:实体参数,有实际的值,在运算上被循环使用的值: 3. 按值传参:按值,就是把实际的值传给函数内部: 4. 指针传 ...

  7. C语言中函数参数传递

    C语言中函数参数传递的三种方式 (1)值传递,就是把你的变量的值传递给函数的形式参数,实际就是用变量的值来新生成一个形式参数,因而在函数里对形参的改变不会影响到函数外的变量的值.(2)地址传递,就是把 ...

  8. C++中为什么要用虚函数、指针或引用才能实现多态?

    原文链接:http://blog.csdn.net/zoopang/article/details/14071779 学过C++的都知道,要实现C++的多态性必须要用到虚函数,并且还要使用引用或者指针 ...

  9. C++ 指针与引用 知识点 小结

    [摘要] 指针能够指向变量.数组.字符串.函数.甚至结构体.即指针能够指向不同数据对象.指针问题 包含 常量指针.数组指针.函数指针.this指针.指针传值.指向指针的指针 等. 主要知识点包含:1. ...

随机推荐

  1. 10 使用 OpenCV、Kafka 和 Spark 技术进行视频流分析

    问题引起 基于分布式计算框架Spark的室内防盗预警系统 首先用摄像头录一段视频,存在电脑里,下载一个ffmpeg的软件对视频进行处理,处理成一张张图片,然后通过hadoop里边的一个文件系统叫做hd ...

  2. [RN] 可播放视频的播放器版本

    可播放视频的播放器版本 "react": "16.6.3", "react-native": "0.57.8", &qu ...

  3. 编写一个方法去掉数组里面重复的内容 var arr=['abc','abcd','sss','2','d','t','2','ss','f','22','d'];

    function noRepeat(arr) { var arr1 = []; for (var i = 0; i < arr.length; i++) { var item = arr[i]; ...

  4. django -- ORM实现作者增删改查

    前戏 前面我们已经实现了出版社的增删改查,书的增删改查,书和出版社的对应关系.现在来写一下作者的增删改查和书的对应关系,那书和作者有什么关系呢?一个作者可以写多本书,一本书可以有多个作者,所以书和作者 ...

  5. 洛谷 P5535 【XR-3】小道消息

    https://www.luogu.com.cn/problem/P5535 伯特兰-切比雪夫定理: 若整数n > 3,则至少存在一个质数p,符合n < p < 2n − 2. 另一 ...

  6. hdu 6620 Just an Old Puzzle(N数码问题)

    http://acm.hdu.edu.cn/showproblem.php?pid=6620 N数码问题: n*n矩阵,里面填着1—n*n-1,还有1个空格, 通过上下左右移动空格的位置, 使矩阵里的 ...

  7. Pandas之csv文件对列行的相关操作

    1.Pandas对数据某一列删除 1.删除列 import pandas as pd df = pd.read_csv(file) #axis=1就是删除列 df.drop(['列名1','列名2'] ...

  8. 剑指offer:机器人的运动范围(回溯法DFS)

    题目描述 地上有一个m行和n列的方格.一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子. 例如,当k为18时,机器人能 ...

  9. 2018-2019-2 20165315《网络对抗技术》Exp9 Web安全基础

    2018-2019-2 20165315<网络对抗技术>Exp9 Web安全基础 目录 一.实验内容 二.实验步骤 1.Webgoat前期准备 2.SQL注入攻击 Command Inje ...

  10. 记录ssis的两个异常解决办法

    1.Foreach文件枚举提示变量为空的解决办法:把foreach属性窗口中的DelayValidation设置为True就可以了 2.csv导入数据库提示:无法在 unicode 和非 unicod ...