C++ C++;:将va_列表类型用作类成员是否安全?

C++ C++;:将va_列表类型用作类成员是否安全?,c++,variadic-functions,C++,Variadic Functions,将va_列表类型用作类成员是否安全 下面的示例适用于Solaris。它不需要跨不同的操作系统进行移植。但它是否可移植到未来的Solaris版本?不同的硬件?不同的编译器?还是编译器选项 class MyFormatString { public: MyFormatString(const char* formatString, va_list varg); ~MyFormatString() { va_end(mVarg); } // ... // pr

将va_列表类型用作类成员是否安全

下面的示例适用于Solaris。它不需要跨不同的操作系统进行移植。但它是否可移植到未来的Solaris版本?不同的硬件?不同的编译器?还是编译器选项

class MyFormatString
{
public:
     MyFormatString(const char* formatString, va_list varg);
     ~MyFormatString() { va_end(mVarg); }
     // ... 
     // provide some util functions to operate on the format string
     // ...
private:
     string mFormatString;
     va_list mVarg;
};

MyFormatString::MyFormatString(const char* fmt, va_list varg)
{
    if (fmt)
        mFormatString=fmt;

    va_copy(mVarg, varg);
}

这在任何平台上都不安全
va_list
指向当构造函数返回时将过时的堆栈参数。考虑使用更多的C++ -ISH类型安全方法来存储参数;可能存储在
std::vector

中,只要在相应的变量函数返回之前销毁所有
MyFormatString
实例,这可能会按预期工作

然而,根据C标准,它仍然是未定义的行为,因为在调用
va\u copy()
的函数返回之前需要调用
va\u end()
,尽管我不知道有哪种实现不足以调用
va\u end()
变量列表
超出范围或相应的变量函数返回之前

如果您正在寻找符合标准的解决方案,请使用
va_列表*
,而不是列表的副本。但是,这将在从相同的
va_列表创建的
MyFormatString
实例之间共享状态,因此它实际上并不等效

如果不想共享状态,则需要手动创建
va_列表的副本
,并将指向该列表的指针传递给构造函数


使用“代码> VAYLISTA//CODE >的平台上的指针是一种数组类型,可以用C++引用来避免(显然C标准中没有说明,但应该根据指针语义来进行操作)。

< P>不,只能使用<代码> VAYLISTU/<代码>,而它所指的对象在范围内。(在函数本身中,或作为参数传递给其他函数),直到调用
va_end
为止。在从函数返回之前,必须调用
va_end
,在该点之后,
va_列表不再可用

来自C99,7.15.1.3:“如果在 返回,行为未定义。“


在C++ 11中,考虑变量模板或<代码> STD::tuple < /C> >作为旧式函数的类型安全替代。< / P> OK,我确信它是这样工作的。它甚至可以在不同OS和编译器上进行移植吗?我的答案是错误的,迈克的正确性:<代码> vAuthEnter()
必须在调用
va_copy()的相同函数中调用
我还阅读了标准C99,7.15.1.3中提到的部分。我想在Solaris中,这种未定义的行为恰好是,这似乎确实有效。我想一种安全的方法是在成员函数中传递va_list*-type并使用va_copy-va_end?或者将va_列表传递给每个成员函数。。。