有时我们无法提前预知应该向函数传递几个实参。例如,我们想要编写代码输出程序产生的错误信息,此时最好用同一个函数实现该项功能,以便对所有的错误处理能够整齐划一。然而,错误信息的种类不同,所以调用错误输出函数时传递的实参也各不相同。
为了编写能处理不同数量实参的函数,c++11新标准提供了两种主要的方法:如果所有的实参类型相同,可以一个名为initializer_list
的标准库类型;如果实参的类型不同,我们可以编写一种特殊的函数,也就是所谓的可变参数模板。
c++还有一种特殊的形参类型(即省略符),可以用它传递可变数量的实参,不过需要注意,此功能一般只用于与c函数交互的接口程序。
1. initializer_list形参
如果函数的实参数量未知,但是实参类型均相同,我们可以用initializer_list
类型的形参。initializer_list
是一种标准库类型,用于表示某种特定类型的值的数组。initializer_list
定义在同名的头文件中,它提供的操作如下所示。
initializer_list<T> lst;
——> 默认初始化,T类型元素的空列表;
initializer_list<T> lst{a, b, c...};
——> lst初始化,lst的元素是const;
lst2(lst); lst2 = lst;
——> 拷贝初始化或者赋值初始化;
lst.size();
——> 列表中的元素数量;
lst.begin();
——> 列表首元素指针;
lst.end();
——> 列表尾后元素指针;
类似vector
,initializer_list
也是一种模板类型,定义initializer_list
时,必须说明列表中所含元素的类型:
1 | initializer_list<string> ls; // initializer_list的元素类型是string |
与vector
不同的是,initializer_list
更加轻量,且initializer_list
对象中的元素均为常量,不可更改。
1 | void error_msg(initializer_list<string> ls) |
2. 可变参数模板
待写。
3. 省略符形参
省略符形参是为了便于c++程序访问某些特殊的c代码而设置的,这些代码使用了名为varargs
的c标准库功能。
注:省略符形参应该仅仅用于c和c++通用的类型。特别注意的是,大多数类类型的对象在传递给省略符形参时都无法正确拷贝。
示例程序如下:
1 | int sum(int count, ...) |
valist
定义在cstdarg,stdarg.h头文件中,用来存储实参列表;va_start(arg_ptr, count);
用来设置首个实参,表示取参数的时候从count的下一个参数开始(不包括count),因此,上例中第一个实参表示后面实参的个数;va_arg(arg_ptr, int);
用来获取实参列表中的实参,int
是实参的类型。它从首个实参依次获取,将获取到的结果作为返回值返回;va_end(arg_ptr);
表示用完arg_ptr,释放内存;
参考文献
《Primer c++》第5版 page 197;