我有以下代码:
#include <cstdarg>
#include <iostream>
using namespace std;
class a {
};
void fun1(a& aa, ...)
{
va_list argp;
va_start(argp, aa);
char *p = 0;
while ((p = va_arg(argp, char *)) != 0) {
cout << p << endl;
}
va_end(argp);
}
void fun2(char *aa, ...)
{
va_list argp;
va_start(argp, aa);
char *p = 0;
while ((p = va_arg(argp, char *)) != 0) {
cout << p << endl;
}
va_end(argp);
}
int main()
{
cout << "fun2" << endl;
fun2("a", "1", "2", (char *)0);
cout << "fun1" << endl;
fun1(a(), "1", "2", (char *)0);
getchar();
}
一切都很好用fun2。但是,fun1只会崩溃。
我是否知道如何防止崩溃,同时能够将类引用用作第一个参数。
目前,它打印:
fun2
1
2
fun1
然后崩溃。
我希望
fun2
1
2
fun1
1
2
答案 0 :(得分:4)
您不能将引用参数用作va_start的最后一个命名参数。原因是因为va_start获取命名参数的地址以查找其余参数的位置。但是,获取引用的地址会给出引用所指向的变量的地址,而不是参数本身的地址。您的选择是:
1)将变量类型从引用更改为指针(如果您对传入的变量的副本没有问题,则更改非引用)。
2)添加一个额外的必需参数,以使引用不是最后一个命名参数。附加参数可以是一个有用的参数,例如您要传递给特定函数的char *之一,或者它可以是您忽略的虚拟变量。
3)更改va_start的定义。不推荐,但你可以做到。有关非便携式重新定义,请参阅http://support.microsoft.com/kb/119394。
答案 1 :(得分:2)
我认为你在fun2
崩溃了。
因为你要多次调用va_arg
并搞砸了堆栈。
您必须只调用va_arg
与参数相同的次数。
答案 2 :(得分:2)
fun1
和fun2
在遇到NULL
或0
参数时都会终止循环。你永远不会传递一个。将main
更改为:
int main()
{
cout << "fun2" << endl;
fun2("a", "1", "2", NULL);
cout << "fun1" << endl;
fun1(a(), "1", "2", NULL);
getchar();
return 0;
}
注意我没有编译过这个,但是应该可以。您可能还必须关注janm's advice。
更新:我放下并再次考虑这个问题。你必须要么:
a
内实例化main
类型的对象并将其传递或... a& aa
中的fun2
更改为a const& aa
当我尝试在g ++下编译原文时,我遇到了以下错误:
错误:'a&amp;'类型的非const引用的初始化无效来自a 暂时的'a'类型 错误:传递'void fun1(a&amp;,...)'
的参数1
基本上,您不能将临时变量作为非const
引用传递。有关一些血腥的详细信息,请参阅this SO question和this Herb Sutter GotW。
答案 3 :(得分:0)
您正在将非const引用传递给临时引用。将fun1原型更改为:
void fun1(a const& aa, ...)
更新
长时间没有使用varargs,错过了终止参数未通过。见D. Shawley's answer;如果您要将其用作界面,则必须传递终止参数。
答案 4 :(得分:0)
我很遗憾听到这段代码不起作用。我注意到如果fun2(aa是ptr而不是ref代码可以工作。我也注意到在尝试编译gcc时(通过http://codepad.org/)你将“a”传递给fun2,这是一个char * .codepad / gcc抱怨它不是一个常量字符*。在键盘中这个代码有效。在我的VS2008副本中它崩溃了,而且2010b2也是。
我的建议是避免使用va params,但我会假设你不能这样,我建议不要使用ref并使用指针。或者切换到gcc但我不会这样做,除非没有其他(合理的)选项。
#include<cstdlib>
#include <cstdio>
#include <ios>
#include <iostream>
using namespace std;
class a {
};
void fun1(a& aa, ...)
{
//cout<< "sizeof" << sizeof(aa) << "&aa == " << &aa;
va_list argp;
va_start(argp, aa);
char *p = 0;
while ((p = va_arg(argp, char *)) != 0) {
cout << p << endl;
}
va_end(argp);
}
void fun2(const char *aa, ...)
{
va_list argp;
va_start(argp, aa);
char *p = 0;
while ((p = va_arg(argp, char *)) != 0) {
cout << p << endl;
}
va_end(argp);
}
int main()
{
cout << "fun2" << endl;
fun2("a", "1", "2", 0);
cout << "fun1" << endl;
a aa;
//cout<< "sizeof" << sizeof(aa) << "&aa == " << &aa;
fun1(aa, "1", "2", 0);
getchar();
}