我有同一个可变参数函数的两个版本,但是一个可以工作,另一个则不能。我怀疑原因是因为一个使用原始类型,而另一个使用 std::string。
void test1(int f_num, ...)
{
va_list file_names;
va_start(file_names, f_num);
for(int i=0; i<f_num; i++)
{
string name = string(va_arg(file_names, char*));
cout << name << endl;
}
va_end(file_names);
}
void test2(int f_num, ...)
{
va_list file_names;
va_start(file_names, f_num);
for(int i=0; i<f_num; i++)
{
string name = va_arg(file_names, string);
cout << name << endl;
}
va_end(file_names);
}
int main()
{
test1(3, "Hallo", "you", "people");
test2(3, "Hallo", "you", "people");
}
上面的结果如下:
Hallo
you
people
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
Aborted (core dumped)
因此第一个函数可以工作,但第二个函数不能。我是否正确地假设这是因为可变参数宏不处理非原始类型?你能让它处理非原始类型吗?
最佳答案
va_arg
解码 va_list
您不能使用va_arg
一次性转换传入的变量参数。 va_arg
的语法是解码变量参数以匹配传入的类型。例如,如果传入 int
值,则必须将其解码为带有 va_arg
的 int
。如果您尝试将其解码为其他任何内容(例如,作为 double
),则会导致未定义的行为。
由于您传入了字符串文字,因此类型应为 const char *
。
const char *arg = va_arg(file_names, const char *);
非平凡类上的 va_arg
是实现定义的
如MSalter's answer清楚地解释了,即使您确实将 std::string
传递给需要变量参数的函数,它也不一定会起作用,因为语义是实现定义的。
When there is no parameter for a given argument, the argument is passed in such a way that the receiving function can obtain the value of the argument by invoking va_arg (18.10). … Passing a potentially-evaluated argument of class type (Clause 9) having a non- trivial copy constructor, a non-trivial move contructor, or a non-trivial destructor, with no corresponding parameter, is conditionally-supported with implementation-defined semantics. …
C++.11 §[expr.call] ¶7
注意:(18.10) 定义了 va_arg
,并且(第 9 条)是 §[class]。
只需使用可变参数模板
您可以使用 C++11 的可变模板参数功能以类型安全的方式实现您想要的效果。假设您实际上想要做的不仅仅是打印每个参数,通常的模式是递归遍历参数包,一次解包一个参数。
void test3 (int f_num, std::string file_name) {
std::cout << f_num << ':' << file_name << std::endl;
}
template <typename... T>
void test3 (int f_num, std::string file_name, T...rest) {
test3(f_num, file_name);
test3(f_num, rest...);
}
因此,迭代是通过递归调用函数来实现的,在下一次递归调用时将参数包减少一个参数。
关于c++ - 是否可以在可变参数函数中处理非原始类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50847671/