以下文章转载自:http://www.jb51.net/article/108390.htm

函数中参数的传递

这里说的传递当然是指 实参是如何传递给形参的啦

还挺复杂的~~~~~~~~⊙﹏⊙b汗,这里讲述了4种参数传递的情况和注意事项:

1.非引用形参

这是最普通,也是最简单的形参传递了。

参数传递,即是使用实参副本(注意啊,是副本,不是实参本身)来初始化形参;

因此,在函数体内对形参的修改不会影响实参的值。

如果形参是指针类型的,那么函数体内是否可以修改指针所指向的对象的值呢?

如果您产生这样的疑问,表示您很有想法~~~

答案是~~~需要分情况讨论。

如果函数的形参是非const类型的指针,则函数可以通过指针实现赋值,修改指针所指向对象的值。

所以,如果需要保护指针指向的值,则形参需定义为指向const对象的指针(注意了,这里的指针依然是非const型的,只是其指向的对象是const型的):

1
2
3
4
5
6
7
void use_ptr(const int *p)
 
{
 
     //use_ptr这个函数可以读指针p所指向的对象,但是不可以修改该对象的值
 
}

const形参

如果函数使用的是非引用非const形参,则既可以给该它传递const实参,也可传递非const实参。

如果函数使用的是非引用const形参,也是既可以给该它传递const实参,也可传递非const实参。那么这两者的差别是什么呢?对于后者,函数连实参的局部副本都不可以改变了。下面是第二种情况的一个例子: void fcn(const int i) {}

复制实参的局限性:复制实参不是在所有的情况下都适合,不是一复制实参的情况如下:

1.当需要在函数中修改实参的值时

2.当需要以大型对象作为实参传递时。对实际的应用而言,复制对象所付出的时间和存储空间代价往往过大

3.当没有办法实现对象的复制时

对于上述几种情况,有效的解决办法是将形参定义为引用或指针类型。

(终于说完这个最简单的传递方式了,╮(╯▽╰)╭)

2.引用形参

引用形参的用法:

1.让函数修改实参的值

2.向主调函数返回额外的结果(本来return就可以返回一个值给主调函数,而且引用参数可以改变实参的值,所以相当于返回了额外的结果)

3.利用const引用避免复制(当向函数传递大型对象时,需要使用引用来提高效率,如果使用引用形参的唯一目的是避免复制实参,则应将形参定义为const引用)

这是一个不适宜复制实参的例子,该函数希望交换两个实参的值

1
2
3
4
5
6
7
8
9
10
11
void swap (int v1,int v2)
 
{
 
  int tmp=v1;
 
  v2=v1;
 
  v1=tmp;
 
}

这个例子期望改变实参本身的值,但是swap无法影响实参本身,执行swap时,指示交换了其实参的局部副本,对实参根本没有改变。解决的方法是:将形参定义为引用类型。

1
2
3
4
5
6
7
8
9
10
11
void swap (int &v1,int &v2)
 
{
 
      int tmp=v1;
 
      v2=v1;
 
      v1=tmp;
 
}

当调用swap(i,j)时,i和j的值才真正实现了交换。

更灵活的指向const的引用

应该将不需要修改的引用形参定义为const引用。普通的非const引用形参在使用时不大灵活。非const引用形参既不能用const对象初始化,也不能用字面值或者产生右值的表达式实参初始化。(如果函数的形参是非const引用形参,表示在函数体内可能会修改该形参值,即会修改实参的值,因此不可以用const对象来做实参传递给这样的函数,所以不灵活。)

传递指向指针的引用

如果想编写一个与前面交换两个整数的swap类似的函数,实现两个指针的交换。已知需用*定义指针,用&定义引用,问题在于,如何将这两个操作符结合起来一获得指向指针的引用。

1
2
3
4
5
6
7
8
9
//交换两个指向整形的指针的值
 
void ptrswap(int *&v1,int *&v2)
 
{
       int=*tmp=v2;
       v2=v1;
       v1=tmp;
 }

形参int *&v1的定义,应该从右至左的理解:v1是一个引用,与指向int型对象的指针相关联。也就是说,v1只是传递ptrswap函数的任意指针的别名。

3.vector和其他容器类型的形参

由于复制vector会使得效率降低,多以如果形参是vector的话,我们常常将该形参声明为引用,避免复制。另一种方法在C++中更为常用,就是通过传递指向容器中需要处理的元素的迭代器来传递容器。

4.数组形参

由于数组是不可以复制的,所以不可以定义使用数组类型形参的函数。如果函数需要使用数组作为形参,那么就要通过操纵指向数组中元素的指针来处理数组。

以下定义都是正确的:

1
2
3
void printValues(int*){}
void printValues(int[]){}
void printValues(int[10]){}

注意了,虽然不能直接传递数组,但是函数的形参可以写成数组的形式。上面三种定义是等价的,形参类洗个都是int*。

通常,将数组形参直接定义为指针要比使用数组语法定义更好。这样就明确地表示,函数操纵的是指向数组元素的指针,而不是数组本身。由于忽略了数组长度,形参定义中如果包含了数组长度则特别容易引起误解。

对于非引用型形参来说,编译器检查数组形参关联的实参时,它只会检查实参是不是指针、指针的形参和数组元素的类型是否匹配,而不会检查数组的长度,所以即使实参数组的长度与形参不匹配时,编译也可以通过,但是在调用时会出错。

但是对于引用型形参来说,编译器还会检查是西安数组的大小与形参的大小是否匹配,所以如果实参数组的长度与形参不匹配,编译时就会报错。

如何确保函数的操作不超出数组实参的边界?

方法有三:

1.在数组本身放置一个标记来检测数组的结束。C风格字符串就是采用这个方法的一个例子,它是一个字符数组,并且以空字符null作为结束的标记。处理C风格字符串的程序就是使用这个标记停止数组元素的处理。

2.使用标准库规范,传递指向数组第一个和最后一个元素的下一个位置的指针。void printValues(const int *beg, const int *end){},如果定义int j[2]={0,1},在调用该函数时,printValues(j,j+2).

3.显式传递表示数组大小的形参。void printValues(const int ia[], size_t size){}

5.可变形参

C++中的省略符形参是为了编译使用了varargs的C语言程序。

1
2
void foo(parm_list,...);
void foo(...);

以上这篇老生常谈C++中实参形参的传递问题就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。

最新文章

  1. 改变Activity启动时的默认动画
  2. github.com/dotnet/orleans
  3. hdu1058丑数(优先队列、暴力打表)
  4. Word快捷键
  5. form表单无刷新提交文件(iframe)
  6. EF性能优化(一)
  7. Linq中小心使用IndexOf
  8. Centos6 下启动httpd报错 Could not reliably determine the server's解决方法
  9. ASP.NET 生命周期(原文翻译)
  10. JAVA线程池应用的DEMO
  11. LINUX文档管理命令
  12. JAVA 学习日记
  13. CPU温度的实现
  14. thinkphp5.1明明密码的一致的 却说不一致的解决办法
  15. 基于Verilog的串口接收程序
  16. Docker CE的安装 与镜像加速
  17. Android开发之将拍摄的图片传至服务器
  18. Android Studio 3.0找不到Android Device Monitor
  19. asp.net页面中实现如果图片不存在则显示默认图片
  20. Mail.Ru Cup 2018 Round 1 virtual participate记

热门文章

  1. xftp找不到匹配的outgoing encryption 算法 怎么解决
  2. 【mysql】之性能优化
  3. 【转】non-blocking REST services with Spring MVC
  4. Jenkins XVnc Plugin
  5. P3811 乘法逆元
  6. Bisecting KMeans (二分K均值)算法讲解及实现
  7. [UE4]Math Expression计算数学公式,可以接受参数
  8. android websocket
  9. How Computers Boot Up.计算机的引导过程
  10. kotlin的安装(一)