转自:http://www.cnblogs.com/jerrychenfly/archive/2010/10/22/1858232.html

下面,我们来看一下,如果在c++的函数中接收数量不定的函数参数。这种形式如同在C#的函数参数列表中使用params 类型的参数。

  我们可以将函数定义成能够接受任意数量的实参。通过将省略号(3个句点...)写在函数定义中形参列表的最后,即可表示调用该函数时可以提供数量可变的实参。例如:

  int sumValues(int first,...)

  {

    //Code for the function

  }

  函数定义中必须至少有一个普通形参,但也可以有多个。省略号必须总是放在形参列表的最后。

  显然,定义中没有关于可变列表中实参的类型或数量的任何信息,因此我们的函数代码必须弄清楚自己被调用时接收的是什么。本地C++库在stdarg.h头文件中定义了va_start、va_arg、和va_end宏,以帮助我们做这件事。用示例来说明其用法是最容易的。

  

  

  #include <iostream>
  #include "stdarg.h"

  using namespace std;

  int sum(int count,...)
  {
     if(count<=0)
        return 0;
     va_list arg_ptr;
     va_start(arg_ptr,count);

    int sum = 0;
     for (int i=0;i<count;i++)
     {
        sum+=va_arg(arg_ptr,int);
     }
     va_end(arg_ptr);
     return sum;
    }

  int main()
  {

    cout<<sum(2,4,6,8,10,12)<<endl;
     cout<<sum(2,22,33,44,55,66,77,88,99)<<endl;
     return 0;
  }

  本例结果:

    10

    55

    按任意键继续。。。

  示例说明

   main()函数函数在两条输出语句中调用了sum()函数,第一次有6个实参,第二次有9个实参。

  sum()函数有一个int类型的普通形参,它表示后面跟着的实参的数量。形参列表中的省略号表明可以传递任意数量的实参。基本上,我们有两种方法来确定调用该函数时有多少实参:第一是像sum()函数一样,用某个固定的形参指定实参的数量;第二是要求最后一个实参具有特殊的标记值,以便我们进行检查和确认。

  为了开始处理可变的实参列表,我们首先声明一个va_list类型的指针:

  va_list arg_ptr;

  va_list 类型是在stdarg.h头文件中定义的,该指针用来依次指向各个实参。

  va_start宏用来初始化arg_ptr,使其指向列表中的第一个实参:

  va_start宏用来初始化arg_ptr,使其指向列表中的第一个实参:

  va_start(arg_ptr,count);

  这个宏的第二个实参是函数形参列表中活力号前面固定形参的名称,用来确定第一个可变实参的位置。

  我们在for循环中取出列表中各个实参的值:

  for (int i=0;i<count;i++)
   {
      sum+=va_arg(arg_ptr,int);
   }

  var_arg宏返回arg_ptr指向的位置存储的实参值,并使arg_ptr递增,以指向下一个实参值。va_arg宏的第二个实参是第一个实参的类型,决定着我们得到的数值以及va_arg递增的方式,因此如果该实参不正确,将造成混乱。程序也许会执行,但我们得到的数值将是无用数据,而且arg_ptr将被错误地递增,从而指向另外的无用数据。

  当结束检索实参值之后,我们用下面这条语句使arg_ptr复位:

  va_end(arg_ptr);

  va_end宏将我们传递给它的实参--va_list类型的指针复位成空值。始终这样做是个好主意,因为在处理过实参之后,arg_ptr将指向某个不包含有效数据的存储单元。

C++ 不定参数(转)的更多相关文章

  1. golang中不定参数与数组切片的区别

    package main import "fmt" func main() { myfunc1(, , , ) //传递不定数量的参数 myfunc2([], , , }) //传 ...

  2. 深入浅出ES6(五):不定参数和默认参数

    作者 Jason Orendorff  github主页  https://github.com/jorendorff 不定参数 我们通常使用可变参函数来构造API,可变参函数可接受任意数量的参数.例 ...

  3. C技巧:结构体参数转成不定参数

    下面这段程序是一个C语言的小技巧,其展示了如何把一个参数为结构体的函数转成一个可变参数的函数,其中用到了宏和内建宏"__VA_ARGS__",下面这段程序可以在GCC下正常编译通过 ...

  4. 不定参数函数原理以及实现一个属于自己的printf函数

    一.不定参数函数原理 二.实现一个属于自己的printf函数 参考博文:王爽汇编语言综合研究-函数如何接收不定数量的参数

  5. C语言函数不定参数实现方式

    函数如何实现不定参数: 由于在C语言中没有函数重载,解决不定数目函数参数问题变得比较麻烦,即使采用C++,如果参数个数不能确定,也很难采用函数重载.对这种情况,提出了指针参数来解决问题. (1)va_ ...

  6. [js高手之路] es6系列教程 - 不定参数与展开运算符(...)

    三个点(...)在es6中,有两个含义: 用在形参中, 表示传递给他的参数集合, 类似于arguments, 叫不定参数. 语法格式:  在形参面前加三个点( ... ) 用在数组前面,可以把数组的值 ...

  7. SE6 不定参数和默认参数详解和使用细节

    在SE5以前我们通常通过arguments类数组对象来引用不定形参,SE6则使用了一种叫做不定参数的写法,比起隐式的arguments要直观的多. 不定参数使用...参数名来指定一个不定参数,参数名指 ...

  8. dataframe的select传入不定参数

    在提取 dataframe 里面的列时,需要传入不定参数,即 dataframe.select(args) .例如某个 dataframe 如下: 一般提取某列或者某几列的时候是这样子写的: data ...

  9. 不定参数对arguments对象的影响

    如果声明函数时定义了不定参数,则在函数被调用时,arguments对象包含了所有传入的参数: function checkArgs(...args){ console.log(args.length, ...

  10. 深入浅出ES6:不定参数和默认参数

    不定参数 我们通常使用可变参函数来构造API,可变参函数可接受任意数量的参数.例如,String.prototype.concat方法就可以接受任意数量的字符串参数.ES6提供了一种编写可变参函数的新 ...

随机推荐

  1. 自己动手写把”锁”之---JMM和volatile

    一.JAVA内存模型 关于Java内存模型的文章,网上真的数不胜数.在这里我就不打算说的很详细.很严谨了.只力求大家能更好的理解和运用,为后边的技术点做铺垫.   内存模型并不是Java独有的概念,而 ...

  2. 7.nginx伪静态规则

    网上收集的一些常用的,要用的时候就仿照一下,或直接拿来用. WordPress伪静态规则 location / { index index.html index.php; if (-f $reques ...

  3. Xamarin~Android篇~监听返回键,单击返回某个webView,双击退出

    https://www.cnblogs.com/lori/p/5088627.html DateTime? lastBackKeyDownTime; public override bool OnKe ...

  4. C# 真正能发邮件的源码

    在网上找了很多例子都试邮件发送都失败,今天无意有试了一下居然行了 public static void ErrorMessageMail(string _subject, string _body)  ...

  5. [js高手之路] html5 canvas教程 - 制作一个数码倒计时效果

    效果图: 这个实例主要注意: 1,剩余时间的计算 2,每个时间数字的绘制 时间主要有0-9和一个冒号组成,用数组来表示( 0: 就是不画圆,1:就是画一个蓝色的圆 ) num.js文件: var di ...

  6. Java学习笔记-嵌套类

    嵌套类 嵌套类有两种类别:static and non-static,分别对应为静态嵌套类和内部类. class OuterClass { ... static class StaticNestedC ...

  7. QCanvasItem介绍-QT3

    QCanvasItem类提供一个在QCanvas上的抽象图形对象. 各种QCanvasItem子类提供立即可用的行为.这个类是一个纯粹的抽象超类,它提供了在所有具体的canvas项目类中共享的行为.Q ...

  8. Markdown 常用语法

    1.标题 # 一级标题 ## 二级标题 ### 三级标题 2.字体 *斜体* **粗体** ~~删除线~~<u>下划线</u> 3.引用 > 引用文字 4.无序列表 - ...

  9. Oracle 触发器的使用

    一.触发器的作用 触发器的作用类似拦截器.把一些针对数据库的DML操作(insert/update/delete/select)进行拦截,符合业务要求的进行操作,不符合要求的操作可以通过抛出异常来阻止 ...

  10. Python多线程编程(第二篇)

    一.Python中的上下文管理器(contextlib模块) 上下文管理器的任务是:代码块执行前准备,代码块执行后收拾 1.如何使用上下文管理器: 如何打开一个文件,并写入"hello wo ...