是否存在使用带参考参数的varargs的问题 [英] Are there gotchas using varargs with reference parameters

查看:123
本文介绍了是否存在使用带参考参数的varargs的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这段代码(总结)...

I have this piece of code (summarized)...

AnsiString working(AnsiString format,...)
{
    va_list argptr;
    AnsiString buff;

    va_start(argptr, format);
    buff.vprintf(format.c_str(), argptr);

    va_end(argptr);
    return buff;
}

在可能的情况下,

AnsiString broken(const AnsiString &format,...)
{
... the rest, totally identical ...
}

我的呼叫代码是这样的: -

My calling code is like this:-

AnsiString s1, s2;
    s1 = working("Hello %s", "World");
    s2 = broken("Hello %s", "World");

但是,s1包含Hello World,而s2具有Hello(null)。我认为这是由于va_start的工作原理,但我不知道发生了什么。

But, s1 contains "Hello World", while s2 has "Hello (null)". I think this is due to the way va_start works, but I'm not exactly sure what's going on.

推荐答案

在va_start展开后,您将看到发生了什么:

If you look at what va_start expands out to, you'll see what's happening:

va_start(argptr, format); 

(大致)

argptr = (va_list) (&format+1);

如果format是一个值类型,它会被放在堆栈的所有可变参数之前。如果格式是引用类型,则只有地址被放置在堆栈上。当你获取引用变量的地址时,你得到地址或原始变量(在这种情况下是在调用Broken之前创建的临时AnsiString),而不是参数的地址。

If format is a value-type, it gets placed on the stack right before all the variadic arguments. If format is a reference type, only the address gets placed on the stack. When you take the address of the reference variable, you get the address or the original variable (in this case of a temporary AnsiString created before calling Broken), not the address of the argument.

如果你不想传递完整的类,你的选择是传递指针,或放入一个哑元参数:

If you don't want to pass around full classes, your options are to either pass by pointer, or put in a dummy argument:

AnsiString working_ptr(const AnsiString *format,...)
{
    ASSERT(format != NULL);
    va_list argptr;
    AnsiString buff;

    va_start(argptr, format);
    buff.vprintf(format->c_str(), argptr);

    va_end(argptr);
    return buff;
}

...

AnsiString format = "Hello %s";
s1 = working_ptr(&format, "World");

AnsiString working_dummy(const AnsiString &format, int dummy, ...)
{
    va_list argptr;
    AnsiString buff;

    va_start(argptr, dummy);
    buff.vprintf(format.c_str(), argptr);

    va_end(argptr);
    return buff;
}

...

s1 = working_dummy("Hello %s", 0, "World");

这篇关于是否存在使用带参考参数的varargs的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆