VAYLIST C++的故障
我只是想写一个非常简单的函数,它的参数个数可变,所以我可以为赋值写一个类似printf的函数。在查看了文档之后,我不确定为什么这段代码总是给我运行时错误: 这是我的密码:VAYLIST C++的故障,c++,arguments,variable-assignment,variadic-functions,C++,Arguments,Variable Assignment,Variadic Functions,我只是想写一个非常简单的函数,它的参数个数可变,所以我可以为赋值写一个类似printf的函数。在查看了文档之后,我不确定为什么这段代码总是给我运行时错误: 这是我的密码: void print(string sOne , ...); void main() { print("first string", "second string", "third String"); system("pause"); } void print(string sOne , ...) {
void print(string sOne , ...);
void main()
{
print("first string", "second string", "third String");
system("pause");
}
void print(string sOne , ...)
{
va_list arguments;
va_start(arguments, sOne);
while ((va_arg(arguments, int)) != 0)
{
string printString = va_arg(arguments, string);
cout << printString;
}
va_end(arguments);
}
你对可变函数的实现是非常不正确的 首先,您需要一种方法来告诉函数有多少个参数或它们何时结束。标准printf通过使用格式说明符来实现这一点。它们的编号表示参数的编号,另一个选项是显式提供编号。您似乎期望最后一个参数是整数0,顺便说一句,但您从未将0作为最后一个参数传递给变量函数 其次,您不能从可变函数参数中以可移植的方式提取std::string。只完全支持普通类型,对于字符串,必须使用char*。字符串不是平凡的,因为它有非平凡的构造函数和析构函数。某些编译器确实支持非平凡类型作为此类函数的参数,但其他编译器不支持,因此您不应该尝试这种方法
最后一点,但并非最不重要:变量函数在C++世界中没有位置,甚至对于赋值也没有。
所以,你的实现有几个问题。 您没有通过对和的呼叫数量的限制: 如果在ap中没有更多参数时调用va_arg,或者如果升级后ap中下一个参数的类型与T不兼容,则行为未定义
您似乎想要打印第一个字符串,因此需要将其作为va_列表的一部分传递,您可以使用计数作为第一个参数来清除1和2:void printint sOne。。。 您正在将const char*s作为参数传递给va_列表,并希望它将这些参数提升为字符串。va_列表不会为您升级。它将您传入的任何内容强制转换为在va_arg中指定的类型,如果您尝试将const char*视为字符串,则会出现运行时错误,如您所见。这可以通过使用字符串作为va_列表参数来纠正:第一个字符串第二个字符串第三个字符串需要使用va_argarguments、const char* 您正在调用va_arg以推进for循环。你需要用一个柜台。调用va_arg提取下一个参数,它们不会测试参数是否可用。相反,使用作为2的一部分传入的计数,自动i=0;我知道++我 进行这些更改会使您的代码看起来像这样:void print(int sOne, ...) {
va_list arguments;
va_start(arguments, sOne);
for (auto i = 0; i < sOne; ++i) {
cout << va_arg(arguments, const char*) << endl;
}
va_end(arguments);
}
SergeyA解释了代码不起作用的原因,下面是一个可能的解决方案:
void print(const char *sOne , ...);
int main()
{
print("first string", "second string", "third String", nullptr);
system("pause");
}
void print(const char *sOne , ...)
{
va_list arguments;
va_start(arguments, sOne);
while (sOne)
{
cout << sOne;
sOne = va_arg(arguments, const char *);
}
va_end(arguments);
}
再次,这个例子是在你必须使用C风格的变量函数的情况下,你应该考虑使用C++的可变模板。Valad函数是元编程的基本要求。@ Jonathan Mee C++有可变模板和初始化列表,你还需要什么?“瓦乌名单只是一份遗产,”杰斯佩朱尔说,他们是。在表达式SFINAE出现之前。你经常需要va_list来利用Varadic模板,尽管我同意在很多情况下,这种模板的封装已经成熟了。@JesperJuhl,我想,他提到了几十年来检查成员是否存在的老把戏。请将您的运行时错误作为问题的一部分发布。@RickSmith我在我的系统上得到的错误中添加了一个,它是由impropper使用调用堆栈中的何处发生错误引起的?@ivan_pozdeev在线:string printString=va_arguments,string;谢谢你发布你的错误。请编辑您的问题,不要使用错误的图像。这将使以后更容易搜索您的问题。未定义的行为。如果在以下情况下调用va_arg。。。升级后ap中下一个参数的类型与T不兼容,行为未定义…@SergeyA我同意。。。但我想你是因为我的答案不正确才发的吧?你能解释一下你的陈述和我说的有什么冲突吗?在这个例子中,实际的论点类型是const char*。std::string不是const char*的兼容类型,并且const char*无法升级为std::string。因此,va_argarguments,string运动未定义的行为。@SergeyA投票前你读过我的答案吗?请密切注意3:以下是详细信息