可变参数
允许函数接受任意数量的额外参数。
由在 函数声明 的 参数列表 之后出现的尾部 ... (除引入包扩展的省略号以外)(自 C++11 起) 表示。
当 参数列表 不为空时,一个可选的逗号可以在 ... 之前,表示一个可变参数函数。这提供了与 C 的兼容性(C 在从 C++ 采用函数原型时添加了对逗号的要求)。
// the function declared as follows int printx(const char* fmt...); // may be called with one or more arguments: printx("hello world"); printx("a=%d b=%d", a, b); int printx(const char* fmt, ...); // same as above (extraneous comma is allowed // for C compatibility) int printy(..., const char* fmt); // error: ... cannot appear as a parameter int printz(...); // valid, but the arguments cannot be accessed portably
注意:这不同于函数 参数包 展开,参数包展开由出现在参数声明符中的省略号表示,而不是出现在所有参数声明之后出现的省略号。参数包展开和“可变”省略号都可能出现在函数模板的声明中,如 std::is_function 的情况。 |
(自 C++11 起) |
内容 |
[编辑] 默认转换
当调用可变参数函数时,在执行左值到右值、数组到指针和函数到指针 转换 后,作为可变参数列表一部分的每个参数都会经历额外的转换,称为默认参数提升
|
(自 C++11 起) |
非 POD 类类型(直到 C++11)作用域枚举和具有合格非平凡复制构造函数、合格非平凡移动构造函数或非平凡析构函数的类类型(自 C++11 起) 在可能求值的调用中具有实现定义的语义而有条件地支持(这些类型始终在 未求值的调用 中支持)。
由于可变参数在 重载解析 的目的中具有最低的等级,因此它们通常用作 SFINAE 中的兜底选项。
在使用可变参数的函数体中,可以使用 <cstdarg>
库设施 访问这些参数的值
定义在头文件
<cstdarg> 中 | |
启用对可变参数函数参数的访问 (函数宏) | |
访问下一个可变参数函数参数 (函数宏) | |
(C++11) |
创建可变参数函数参数的副本 (函数宏) |
结束对可变参数函数参数的遍历 (函数宏) | |
保存 va_start、va_arg、va_end 和 va_copy 所需的信息 (typedef) |
如果省略号之前的最后一个参数是引用类型,或者其类型与默认参数提升后的类型不兼容,则va_start宏的行为是未定义的。
(自 C++11 起) |
[编辑] 替代方法
|
(自 C++11 起) |
[编辑] 说明
在 C 编程语言中,直到 C23,至少需要在省略号参数之前出现一个命名参数,因此R printz(...);在 C23 之前是无效的。在 C++ 中,这种形式是允许的,即使传递给此类函数的参数不可访问,并且通常用作SFINAE中的回退重载,利用省略号转换在重载解析中的最低优先级。
这种可变参数语法是在 1983 年的 C++ 中引入的,省略号之前没有逗号。当 C89 从 C++ 中采用函数原型时,它用需要逗号的语法替换了该语法。为了兼容性,C++98 接受 C++ 风格的f(int n...)和 C 风格的f(int n, ...)。
逗号可用于简化的函数模板,使省略号表示可变参数函数而不是可变参数模板 void f1(auto...); // 与 template<class... Ts> void f3(Ts...) 相同 |
(自 C++20) |
[编辑] 缺陷报告
以下行为更改缺陷报告已追溯应用于先前发布的 C++ 标准。
DR | 应用于 | 发布的行为 | 正确的行为 |
---|---|---|---|
CWG 506 | C++98 | 将非 POD 类参数传递给 省略号导致未定义的行为 |
传递此类参数是 有条件支持的,具有 实现定义的语义 |
CWG 634 | C++98 | 有条件支持的类类型 使某些 SFINAE 习惯用法无法正常工作 |
如果未评估,则始终支持 |
CWG 2247 | C++11 | 对传递参数没有限制 包或 lambda 捕获到 va_start |
使其无效, 无需诊断 |
CWG 2347 | C++11 | 尚不清楚是否将作用域枚举传递给 省略号会受到默认参数提升的影响 |
传递作用域枚举 是条件支持的,具有 实现定义的语义 |
[编辑] 另请参阅
C 文档 for 可变参数
|