如何在 C++ 中使用以下形式的函数:void function(...) {}
?
真的需要至少一个隐式参数吗?
从评论中重复:
在这里,C99 和 C++11 之间似乎有一个有趣的区别:C++11 允许函数声明void foo(...)
,因为参数声明子句中的参数声明列表是可选的:[dcl.fct]
函数声明:
D1 (
参数声明子句)
cv-qualifier-seq opt ref-qualifier opt异常规范opt attribute-specifier-seq opt
参数:
参数声明子句:
参数声明列表opt...
opt
参数声明列表, ...
(注意parameter-declaration-list和...
是如何在此处单独选择的,这意味着您可以省略其中一个或两者。clang++ 和 g++ 支持这种解释。)
在 C99 中,不允许此声明,因为参数列表在参数类型列表中不是可选的:6.7.5/1
函数声明:
直接声明器
(
参数类型列表)
参数:
参数类型列表:
参数列表
参数列表, ...
由于等宏/函数是从 C99 继承的,因此无法在 C++ 中va_start
使用与省略号匹配的参数和空的参数声明列表。
C99 中的描述va_start
:7.15.1.4
void va_start(va_list ap,
parmN);
[...]
参数parmN是函数定义中可变参数列表中最右边参数的标识符(在 之前的那个, ...
)。[...]
强调我的。C99假定在省略号之前有一个参数,因为在 C99 中声明一个带有省略号但没有参数的函数是不合法的。
然而,我可以看到在 C++ 中使用带有省略号但没有任何参数的函数的两个原因:
如果您想保持某种平台独立性,您至少需要一个参数并使用 va_arg 宏。
如果您了解架构和调用约定的低级细节,那么您可以直接从寄存器和/或堆栈中提取参数(取决于各种参数的最终位置)。
鉴于va_start
“函数”需要一个参数来设置va_list
,我想说不可能以可靠且可移植的方式做到这一点。很可能会找到适用于特定平台的东西 - 但如果您更改编译器,为不同的平台编译,并且在某些情况下即使您使用不同的编译器选项进行编译(或更改函数中的代码,例如引入局部变量)。
...
va_list vl;
va_start(vl, arg);
...
当然,您的另一个问题是知道什么时候没有参数(这将是一个有效的案例)。因此,如果您没有至少一个参数,那么当您根本不传递任何参数时会发生什么?你怎么“知道”这种情况?