html5手机网站分辩率,品质好的女装品牌,厦门网站建设是什么意思,wordpress china第三性目录 引言 库的基本功能
va_start 宏:
va_arg 宏
va_end 宏
va_copy 宏
使用 处理可变参数代码
C11可变参数模板
基本概念
sizeof... 运算符
包扩展 引言 在C编程中#xff0c;处理不确定数量的参数是一个常见的需求。为了支持这种需求#xff0c;C标准库提供了 11可变参数模板
基本概念
sizeof... 运算符
包扩展 引言 在C编程中处理不确定数量的参数是一个常见的需求。为了支持这种需求C标准库提供了 stdarg.h 头文件其中定义了一组宏和类型用于处理不定参数函数。C继承了C语言的可变参数机制使用了stdarg.h提供的宏来处理不确定数量的参数。其原理基于栈的推入和弹出过程不需要明确参数数量。此外C提供了可变参数机制让我们能够创建接收任意数量参数的函数。这一特性在许多实际应用中非常有用比如日志记录、函数重载等。 stdarg.h 库的基本功能
stdarg.h 库包含以下主要部分
va_start 宏:
用于初始化 va_list 变量其基本语法如下
void va_start(va_list ap, last);
apva_list 变量。last最后一个确定的参数后面的参数是可变参数。 va_arg 宏 va_arg 宏用于访问可变参数列表中的下一个参数其基本语法如下
type va_arg(va_list ap, type);
apva_list 变量。type要访问的参数的类型。
va_end 宏 va_end 宏用于结束 va_list 变量的访问其基本语法如下
void va_end(va_list ap); apva_list 变量。 va_copy 宏 va_copy 宏用于复制 va_list 变量其基本语法如下
void va_copy(va_list dest, va_list src);
dest目标 va_list 变量。src源 va_list 变量。
使用 stdarg.h 处理可变参数代码 示例中print_args接收一个格式字符串然后根据格式字符i表示整数d表示双精度浮点数解析后面的参数。
#include iostream
#include cstdargvoid print_args(const char* fmt, ...)
{va_list args;va_start(args, fmt);while (*fmt ! \0) {if (*fmt i) {int i va_arg(args, int);std::cout int: i std::endl;} elseif (*fmt d) {double d va_arg(args, double);std::cout double: d std::endl;}fmt;}va_end(args);
}int main()
{print_args(ddii, 0.618,3.14, 7, 9);return 0;
}
//double: 0.618 double: 3.14 int: 7 int: 9
C11可变参数模板
基本概念 C11通过模板提供了类型安全且灵活的可变参数机制。可以通过递归模板来处理不同类型的参数避免了手动处理类型的麻烦。也就是支持可变数量参数的函数模板和类模板可变数目的参数被称为参数包。
参数包有两种类型:
模板参数包表示零或多个模板参数使用class...或typename...关键字声明。函数参数包表示零个或多个函数参数使用类型名后跟...表示。
templateclass ...Arg void Func(Arg... arg) {}
templateclass ...Arg void Func(Arg... arg) {}
templateclass ...Arg void Func(Arg... arg) {} 我们用省略号...来指出一个模板参数或函数参数的表示一个包在模板参数列表中class...或typename...指出接下来的参数表示零或多个类型列表在函数参数列表中类型名后面跟...指出接下来表示零或多个形参对象列表。可变参数模板的原理跟模板类似本质还是去实例化对应类型和个数的多个函数。
sizeof... 运算符
sizeof...运算符来计算参数包中参数的个数。
template class ...Arg
void PrintArgNum(Arg... arg)
{cout sizeof...(arg)个参数包 endl;
}int main()
{double a 3.14;PrintArgNum();PrintArgNum(a);//一个参数PrintArgNum(1, string(241564132));//两个参数return 0;
} 编译本质会结合引用折叠规则实例化出以下三个函数在类型泛化基础上叠加了数量变化让泛型编程更加灵活。
void Print();
void Print(double arg1);
void Print(int arg1, string arg2);包扩展 对于一个参数包我们除了计算它的参数个数还可以对它进行包扩展。我们还要提供用于每个扩展元素的模式扩展一个包就是将他分解为构成的元素对每个元素应用模式获得扩展后的列表。我们通过在模式的右边放省略号(...)来触发扩展操作。
//参数包是0个时直接匹配这个函数
void ShowList()
{cout endl;
}templateclass T,class ...Arg
void ShowList(T val,Arg... arg)
{cout val endl;//arg是N个参数的参数包调用Printf,参数包的第一个传给val剩下N-1个传给参数包ShowList(arg...);
}
template class ...Arg
void Print(Arg... arg)
{cout sizeof...(arg)个参数包 endl;ShowList(arg...);
}int main()
{double x 3.14;Print();Print(11.1);//一个参数Print(1, string(bjkbhv));//两个参数Print(12.55, string(9jjug7), x);//三个参数return 0;
} 实际上是通过递归展开来实现的当参数包为空时就会调用 void ShowList()同时终止递归
递归时T接受传来参数包的第一个参数类型arg接受其余的参数类型以此往复。