【C++再学习】【03】函数形参实参与值传递引用传递新解
来源:互联网 发布:探索者软件 编辑:程序博客网 时间:2024/05/20 06:05
一开始没觉得这部分还需要整理一下,仔细看过书之后发现还有点意思,所以整理记录下来。根据传递方法的不同分成两大类整理,分别为继承自C的值传递以及C++新增的引用传递。
一、值传递
先看两行再简单不过的代码:
int a = 10;
int b = a;
这是用一个变量去给另一个变量赋值的代码,经过这种赋值后b可以随便改变自己的值,但是不影响a的值,我想说的是:函数的值传递方式的本质就是变量间的赋值。下边再给两个经典例子:
void swap1(int a,int b)
{
int temp = a;
a = b;
b = temp;
}
void swap2(int* a,int *b)
{
int* temp =a;
a = b;
b = temp
}
x=1,y=2;
swap1(x,y);
swap2(&x,&y);
在调用swap1(x,y)函数的时候,我们知道这是典型的值传递,调用之后x,y的值并没有改变,但是在调用swap2(&x,&y)函数后,x,y的值发生了改变,这还是值传递么?答案是肯定的,这仍然是值传递,只不过这时赋值的是地址所以可以通过地址改变原有的参数值。可以看这样的两行代码:
int a = 10;
int * b = &a;
这也是用一个变量去给另外一个变量赋值,只不过此时使用地址去赋值,所以任何通过b指针去改变它所指向地址的值时,a也会受到影响。
所以,值传递的特点是:在函数调用时,系统会在函数作用域新建形参存储空间并用实参对其初始化,所以调用时形参是实参的一个副本。上面的swap1与swap2函数都是典型的值传递方式。
二、引用传递
首先说一下,引用是C++新增加的特性。同样,先看两行代码:
int a = 10;
int &b = a;
此处的&符号并不是取地址的意思,而是声明b是a的引用,俗话就是说b是a的别名或者是代言人,b有什么变化就会同步到a上。函数的引用传递的本质就是这种引用赋值。下边再给个经典的例子:
void swap3(int& a,int& b)
{
int temp = a;
a = b;
b =temp;
}
x=1,y=2;
swap3(x,y);
在调用swap3(x,y)之后x,y的值发生的变化,这就是引用传递,函数内部的a和b成为x和y的别名,任何对a和b的更改都会同步到x和y。
三、值传递与引用传递的思考
我们来对比一下两种传递方式:值传递需要复制实参内存内容以初始化形参,所以会带来一些开销,可能对于内置类型的参数开销可以忽略不计,但是对于大型的类对象来说,复制的代价会很大,虽然C语言也提供像上边swap2函数形式的“指针式”值传递方法,只传递过去一个地址,可以解决传递大的对象的复制开销问题,然而很多人对指针的安全问题一直都有很多看法。从这个角度出发,C++新提出了引用传递,可以达到“指针式”值传递的效果,同时不会带来很多安全问题。
四、普通形参、普通实参、const形参、const实参
在函数的形参实参问题中,还有一些要注意的问题:
先看这样一个例子:
void fun(const int * p)
{
......
}
int a = 10;
const int b = 20;
fun(&a);
fun(&b);
我们知道,如果不想让函数修改实参的值,我们可以将函数的形参定义为const类型,在上边代码中,用了两种实参类型去调用函数,一种是普通实参,一种是const实参,实际上这两种都是正确的。因为const指针既可以用普通的变量地址初始化,也可以用const变量地址初始化。
再看看另外一个例子:
void fun(int * p)
{
......
}
int a = 10;
const int b = 20;
fun(&a);
fun(&b);
上边代码中函数形参为普通形参,而调用的时候用了两种类型实参,一种是普通变量a另一种是const变量b,前一种没有问题,后边这种实际上时错误的,编译器将禁止这种调用方式,也就是说不能用const实参去初始化普通形参,因为不能保证函数内部不会更改const实参的值。
另外,有一些小提醒:
1、在不希望函数内部修改实参时,尽量将函数的形参定义成const类型,这样一方面保证了实参不会发生变化,另一方面这种函数既可以接受const类型的实参调用又可以接受普通类型的实参调用,如果不用const形参那么将不能接受const实参类型调用,带来很多限制。
2、有时候,我们希望函数不止有一个返回值,如果仅仅用return返回语句将不好实现,此时,可以在函数的形参列表中专门定义一个可以保存返回值的形参,一般定义为非const的引用类型或者指针类型,通过在函数内部给这样的这样的实参赋值就可以达到返回更多值得效果。
- 【C++再学习】【03】函数形参实参与值传递引用传递新解
- 值传递、引用传递和形参、实参
- Java值传递和引用传递及形参实参的分析(实例对比c++)
- C语言再学习 -- 值传递,址传递,引用传递
- 指针与引用(函数形参的值传递,引用传递,指针传递)
- 形参与实参, 值传递与引用传递, ref参数与out参数
- C/C++函数形参传实参时值传递、指针传递、引用传递的区别
- C/C++函数形参传实参时值传递、指针传递、引用传递的区别
- C语言-实参到函数形参传递的理解
- C/C++函数传参:值传递、参数传递、引用
- 实参与形参的传递关系
- C中实参与形参的“值传递”只能“单向传送”(透彻的理解)
- 图解C/C++中函数参数的值传递、指针传递与引用传递
- 图解C/C++中函数参数的值传递、指针传递与引用传递
- 传递给const引用形参的实参要求
- 函数的形参传递方式:值传递,指针传递,引用传递的区别
- C#形参,实参,值传递参数,引用传递参数,输出参数,参数数组的学习
- 值传递和地址传递 实参和形参
- 移动游戏的网络通信层设计
- Python3.4每次处理一个字符
- 试试看
- 【CQOI2006】凸多边形
- case语句后面不能直接创建对象的问题
- 【C++再学习】【03】函数形参实参与值传递引用传递新解
- 初探iptables -- 下
- 黑马程序员-----反射
- Comparable vs Comparator in Java
- Seoquake参数解释和如何使用
- cvReshape比cvTranspose,cvGetRow,cvSetRow
- Android 图像缩略图及压缩图像
- 《自由从何而来》 读书笔记
- ASP.NET编写代码时出现“意外的字符”该怎么处理