gpt4 book ai didi

c++ - 是否可以在可变参数函数中处理非原始类型?

转载 作者:搜寻专家 更新时间:2023-10-31 01:29:00 25 4
gpt4 key购买 nike

我有 2 个版本的相同可变参数函数,但是一个有效,另一个无效。我怀疑原因是因为一个使用原始类型而另一个使用 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_argint。如果您尝试将其解码为任何其他内容(例如,作为 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,而(Clause 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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com