C++深入学习笔记(7)——含有可变形参的函数

有时候我们无法提前预支应该向函数传递几个参数。例如,我们想要编写代码输出程序产生的错误信息,此时最好用同一个函数实现该功能,一遍对所有错误的处理能够整齐划一。然而,由于错误信息的种类不同没所以调动错误输出函数时传递的实参也各不相同。

1.initializer_list形参

        如果函数的实参数量未知但是全部实参的类型都相同,我们可以使用initialist_list类型的形参。initializer_list是一种标准库类型,用于表示某种特定类型的值的数组。它定义在同名的头文件中。

1.1 initializer_list提供的操作

initializer_list<T> list;        // 默认初始化,T类型元素的空列表
initializer_list<T> list{a, b, c};        
// list元素的数量和初始值一样多;list的初始值是列表中元素的副本;lsit列表中的元素都是const型

list_1(list);        // 拷贝或赋值一个initializer_list对象不会拷贝列表中的元素;拷贝后原始
list_2 = list;        // 列表和副本共享元素

list.size();        // 返回list中列表元素的个数
list.begin();        // 返回list中列表首元素的指针
list.end();        // 返回list中列表尾元素的下一个地址的指针

和vector一样,initializer_list也是一种模板类型,定义initializer_list对象时必须说明所含元素的类型。

和vector不一样的是,initializer_list所含的元素永远是const型(即常量值),我们永远无法改变initializer_list对象所含元素的值。

1.2 遍历initializer_list对象

#include<iostream>
#include<string>
#include<initializer_list>

using namespace std;

int main()
{
    initializer_list<string> list{"first", "second", "third", "forth"};
    // 范围for循环
    for(const auto &elem : list)
        cout << elem << " ";
    
    cout << endl;

    // 传统for循环
    for(auto beg = list.begin(); beg != list.end(): ++beg)
        cout << *beg << " ";
    cout << endl;
}

first second third forth

first second third forth

1.3传递initializer_list型参数

        如果你想向initializer_list形参中传递一个值的序列,则必须把序列放在一对大括号里。

if (expected != actual)
    error_msg({"function", expected, actual});
else
    error_msg({"function", "okey"});

1.4 C风格的可变参数列表——省略符形参

有时,您可能会碰到这样的情况,您希望函数带有可变数量的参数,而不是预定义数量的参数。C 语言为这种情况提供了一个解决方案,它允许您定义一个函数,能根据具体的需求接受可变数量的参数。下面的实例演示了这种函数的定义。

1

2

3

4

5

6

7

8

9

10

11

12

int func(int, ... )

{

   .

   .

   .

}

int main()

{

   func(223);

   func(3234);

}

请注意,函数 func() 最后一个参数写成省略号,即三个点号(...),省略号之前的那个参数是 int,代表了要传递的可变参数的总数。为了使用这个功能,您需要使用 stdarg.h 头文件,该文件提供了实现可变参数功能的函数和宏。具体步骤如下:

  • 定义一个函数,最后一个参数为省略号,省略号前面可以设置自定义参数。
  • 在函数定义中创建一个 va_list 类型变量,该类型是在 stdarg.h 头文件中定义的。
  • 使用 int 参数和 va_start 宏来初始化 va_list 变量为一个参数列表。宏 va_start 是在 stdarg.h 头文件中定义的。
  • 使用 va_arg 宏和 va_list 变量来访问参数列表中的每个项。
  • 使用宏 va_end 来清理赋予 va_list 变量的内存。

现在让我们按照上面的步骤,来编写一个带有可变数量参数的函数,并返回它们的平均值:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

#include <stdio.h>

#include <stdarg.h>

double average(int num,...)

{

    va_list valist;

    double sum = 0.0;

    int i;

    /* 为 num 个参数初始化 valist */

    va_start(valist, num);

    /* 访问所有赋给 valist 的参数 */

    for (i = 0; i < num; i++)

    {

       sum += va_arg(valist, int);

    }

    /* 清理为 valist 保留的内存 */

    va_end(valist);

    return sum/num;

}

int main()

{

   printf("Average of 2, 3, 4, 5 = %f\n", average(42,3,4,5));

   printf("Average of 5, 10, 15 = %f\n", average(35,10,15));

}

当上面的代码被编译和执行时,它会产生下列结果。应该指出的是,函数 average() 被调用两次,每次第一个参数都是表示被传的可变参数的总数。省略号被用来传递可变数量的参数。

复制代码

1

2

Average of 2345 3.500000

Average of 51015 10.000000

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值