And*_*hin 31 c c++ syntax variadic-functions
如何在C++中的函数中包含可变数量的参数.
C#中的模拟:
public void Foo(params int[] a) {
for (int i = 0; i < a.Length; i++)
Console.WriteLine(a[i]);
}
public void UseFoo() {
Foo();
Foo(1);
Foo(1, 2);
}
Run Code Online (Sandbox Code Playgroud)
Java中的模拟:
public void Foo(int... a) {
for (int i = 0; i < a.length; i++)
System.out.println(a[i]);
}
public void UseFoo() {
Foo();
Foo(1);
Foo(2);
}
Run Code Online (Sandbox Code Playgroud)
Ste*_*202 44
这些被称为Variadic函数.维基百科列出了C++的示例代码.
要在C编程语言中可移植地实现可变参数函数,应使用标准的stdarg.h头文件.旧的varargs.h标头已被弃用,转而使用stdarg.h.在C++中,
cstdarg应该使用头文件.要创建可变参数函数,
...必须在参数列表的末尾放置省略号().在函数体内,va_list必须定义一个类型的变量.随后,宏va_start(va_list, last fixed param),va_arg(va_list, cast type),va_end(va_list)都可以使用.例如:
#include <stdarg.h>
double average(int count, ...)
{
va_list ap;
int j;
double tot = 0;
va_start(ap, count); //Requires the last fixed parameter (to get the address)
for(j=0; j<count; j++)
tot+=va_arg(ap, double); //Requires the type to cast to. Increments ap to the next argument.
va_end(ap);
return tot/count;
}
Run Code Online (Sandbox Code Playgroud)
rub*_*nvb 15
真正的C++解决方案是可变参数模板.您需要一个相当新的编译器,并在需要时启用C++ 11支持.
处理"使用所有函数参数做同样事情"问题的两种方法:递归地,并且具有丑陋(但非常符合标准)的解决方案.
该递归解决方案看起来有点像这样:
template<typename... ArgTypes>
void print(ArgTypes... args);
template<typename T, typename... ArgTypes>
void print(T t, ArgTypes... args)
{
std::cout << t;
print(args...);
}
template<> void print() {} // end recursion
Run Code Online (Sandbox Code Playgroud)
它为每个参数集合生成一个符号,然后为递归的每个步骤生成一个符号.至少可以说这不是最理想的,所以SO的优秀C++人员想到了滥用列表初始化的副作用的一个很好的技巧:
struct expand_type {
template<typename... T>
expand_type(T&&...) {}
};
template<typename... ArgTypes>
void print(ArgTypes... args)
{
expand_type{ 0, (std::cout << args, 0)... };
}
Run Code Online (Sandbox Code Playgroud)
代码不是为一百万个略有不同的模板实例生成的,作为奖励,您可以获得函数参数的保留顺序.有关此解决方案的详细信息,请参阅其他答案.
在C ++ 11及更高版本中,您也可以使用初始化列表。
int sum(const initializer_list<int> &il)
{
int nSum = 0;
for (auto x: il)
nSum += x;
return nsum;
}
cout << sum( { 3, 4, 6, 9 } );
Run Code Online (Sandbox Code Playgroud)
除了其他答案,如果你只是想传递一个整数数组,为什么不:
void func(const std::vector<int>& p)
{
// ...
}
std::vector<int> params;
params.push_back(1);
params.push_back(2);
params.push_back(3);
func(params);
Run Code Online (Sandbox Code Playgroud)
但是,您无法在参数,表单中调用它.您必须使用答案中列出的任何可变参数函数.C++ 0x将允许可变参数模板,这将使其类型安全,但现在它基本上是内存和转换.
你可以模拟某种可变参数 - >向量的东西:
// would also want to allow specifying the allocator, for completeness
template <typename T>
std::vector<T> gen_vec(void)
{
std::vector<T> result(0);
return result;
}
template <typename T>
std::vector<T> gen_vec(T a1)
{
std::vector<T> result(1);
result.push_back(a1);
return result;
}
template <typename T>
std::vector<T> gen_vec(T a1, T a2)
{
std::vector<T> result(1);
result.push_back(a1);
result.push_back(a2);
return result;
}
template <typename T>
std::vector<T> gen_vec(T a1, T a2, T a3)
{
std::vector<T> result(1);
result.push_back(a1);
result.push_back(a2);
result.push_back(a3);
return result;
}
// and so on, boost stops at nine by default for their variadic templates
Run Code Online (Sandbox Code Playgroud)
用法:
func(gen_vec(1,2,3));
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
68758 次 |
| 最近记录: |